I'm glad to say I have had some success.  Based on Jake's recommendations, I
used the ContextClassLoaderSelector from Log4j CVS with success.  I also
avoided the OptionConverter class and used the PropertyConfigurator and
DOMConfigurator classes instead.  I think I also had not initialised log4j
in my service thread correctly, after setting the context class loader.

Many thanks to both Jake and Carl for your help and advice.

Vance

-----Original Message-----
From: Jacob Kjome [mailto:[EMAIL PROTECTED] 
Sent: Saturday, 20 March 2004 12:23 AM
To: Log4J Users List
Subject: RE: Contextual Repository Selector problem

Quoting Vance Karimi <[EMAIL PROTECTED]>:

> Hi Jake,
> I actually read through the Log4j CVS ContextClassLoaderSelector and
servlet
> specific package java files.  They were very helpful and documented
> extremely well.
> 
> Forgive me if I'm just re-stating the obvious.
> 
> If I understand it right, the init method of InitServlet is called by the
> container.  This is called once per context start-up right?
> 

Yes, but note that one would want to use InitContextListener, not
InitServlet,
but that's a bit off-topic for this discussion.


> This method performs the initializeLog4j task which sets the
> RepositorySelector by creating a new instance of
ContextClassLoaderSelector,
> if one is not already created.

Actually, the InitShutdownController does all this in the
setSelector(ServletContext) method and simply attempts each time to set the
repository selector.  It then catches various exceptions that might occur if
the
repository selector is already set.  It can only be set once unless provided
with the original guard object which was used to initially set it.  Of
course,
this is per Log4j instance.  If one has log4j.jar in each app's WEB-INF/lib,
then each will set a selector successfully since none of the apps can see
each
other's classloader.  The real reason for using a repository selector is
when
there is a single global log4j.jar that everyone uses.

For info on this method, see the original source at...
http://tinyurl.com/3aw7q

 Having done that, it will load the log4j
> properties or xml file associated with the context.
> 

It should, although automatic configuration won't happen after the first
time
Log4j is loaded up in a classloader.  Upon server startup, Log4j will look
for
the config file, but not after that.  Apps would have to initialize Log4j
themselves in this environment, unless they put Log4j in their WEB-INF/lib
directories.  But then that is a whole new instance of Log4j with no
particular
reason to be using a repository selector except for guarding against the
case
where the app doesn't include Log4j.jar in WEB-INF/lib.  Of course, setting
the
repository selector should normally be done by the container.  The code in
InitShutdownController is Kludge for making sure one exists before doing
configuration in case the server hasn't set it (because almost none I know
of do).

> Only 1 instance of the ContextClassLoaderSelector is created and set using
> LogManager so that we can track each Hierarchy based on the context
> classloader.

Sounds right

> 
> I believe I do all of that, however I do not manually call
> PropertyConfigurator or DOMConfigurator.  I use
> OptionConverter.selectAndConfigure, as it should determine if the log4j
> config file is an xml or properties file and call the corresponding
> Configurator.
> 

To be honest, I've never looked at OptionConverter.  I'll have to do that
sometime.  

> The other difference I see is that I call
OptionConverter.selectAndConfigure
> in my getLoggerRepository implementation method.

I would avoid this.  That is not the place to do configuration.  That's an
app's
responsibility.

  My understanding is that
> when I call Logger.getLogger(..) and having set the
> Thread.currentThread().contextClassLoader, a new
LoggerRepository/Hierarchy
> will be created or looked up if already exists.  I can't see why it would
> make a difference if I manually call the
OptionConverter.selectAndConfigure
> when a new context is about to run for the first time.  But, it is
something
> I will try.
> 

Yes, try that.  You might want to just try the existing
ContextClassLoaderSelector in logging-log4j-sandbox (
http://tinyurl.com/32htr )
and see if that works for you.  If it does, then you know the problem is in
your
code somewhere.  If that doesn't work for you, then you know to look
elsewhere.
 In that case, ask back here because I'd be very interested in knowing it is
not
working in certain cases.

> If you have any other thoughts, I'd appreciate them.
> 

Hopefully what I've provided will get you back on track.  Let me know if it
doesn't.  Also let me know of any success you may have.

> Cheers,
> Vance
> 

Jake

> -----Original Message-----
> From: Jacob Kjome [mailto:[EMAIL PROTECTED]
> Sent: Friday, 19 March 2004 2:31 AM
> To: Log4J Users List
> Subject: Re: Contextual Repository Selector problem
> 
> I don't have much time to respond, but there already exists
implementations
> of
> repository selectors in the latest Log4j CVS
(ContextJNDIRepositorySelector)
> and
> in the latest Log4j sandbox CVS (ContextClassLoaderSelector).  I added
lots
> of
> instructions to them.  Also look in InitShutdownController (in Log4j
> sandbox) to
> see how I initialize the repository selector.  See more here...
> 
>
http://nagoya.apache.org/wiki/apachewiki.cgi?Log4JProjectPages/AppContainerL
> ogging
> 
> 
> Jake
> 
> Quoting Vance Karimi <[EMAIL PROTECTED]>:
> 
> > Hi
> > I am writing a container server application that runs services/contexts
> > within it.  These services are hot deployed in a jar file and I manage
the
> > ClassLoaders to handle separate contexts.  I need to implement the
> > repository selector in Log4j so each thread that runs a service logs to
a
> > separate log file.
> >
> > Based on the following http://www.qos.ch/logging/sc.html I have a
> Repository
> > Selector something very similar to:
> >
> >
> > import org.apache.log4j.spi.RepositorySelector;
> > import org.apache.log4j.spi.LoggerRepository;
> > import org.apache.log4j.spi.RootCategory;
> > import org.apache.log4j.Hierarchy;
> > import org.apache.log4j.Level;
> > import java.util.Hashtable;
> >
> > public class CRS implements RepositorySelector {
> >
> >   // key: current thread's ContextClassLoader,
> >   // value: Hierarchy instance
> >   private Hashtable ht;
> >
> >   public CRS() {
> >    ht = new Hashtable();
> >   }
> >
> >   public LoggerRepository getLoggerRepository() {
> >     LoggerRepository loggerRepository = null;
> >
> >     ClassLoader classLoader =
> > Thread.currentThread().getContextClassLoader();
> >
> >     loggerRepository = (LoggerRepository)
> > loggerRepositories.get(classLoader.toString());
> >
> >     if (loggerRepository != null) {
> >                     // do nothing
> >     } else {
> >       loggerRepository = new Hierarchy(new RootCategory((Level)
> > Level.DEBUG));
> >     loadRepository(loggerRepository);
> >     loggerRepositories.put(classLoader.toString(), loggerRepository);
> >
> >     }
> >
> >     return loggerRepository;
> >   }
> >
> >   /**
> >    * The Container should remove the entry when the web-application
> >    * is removed or restarted.
> >    * */
> >   public void remove(ClassLoader cl) {
> >     if (loggerRepositories.containsKey(cl.toString())) {
> >       LoggerRepository lr = (LoggerRepository)
> > loggerRepositories.get(cl.toString());
> >     lr.resetConfiguration();
> >     }
> >     loggerRepositories.remove(cl.toString());
> >   }
> >
> >   private static void loadRepository(LoggerRepository loggerRepository)
{
> >
> >     URL url = getURL(resources);
> >
> >     if (url != null) {
> >       OptionConverter.selectAndConfigure(url, null, loggerRepository);
> >     }
> >   }
> > .....
> > }
> >
> >
> > I set the Context Repository Selector when the server first starts up:
> >
> >   if (guard == null) {
> >     guard = new Object();
> >   }
> >
> >   ContextRepositorySelector crs =
> agent.registerContextRepositorySelector();
> >   LogManager.setRepositorySelector(crs, guard);
> >
> >
> > I have enabled debugging in Log4j.  When my server first starts up, I
get
> > the following debug statements due to the log4j.properties of the
server,
> > showing the root context and 2 appenders (Default and Console)
> >
> > log4j: Parsing for [root] with value=[DEBUG, Default, Console].
> > log4j: Level token is [DEBUG].
> > log4j: Category root set to DEBUG
> > log4j: Parsing appender named "Default".
> > log4j: Parsing layout options for "Default".
> > log4j: Setting property [conversionPattern] to [%d [%t] %-5p %c - %m%n].
> > log4j: End of parsing for "Default".
> > log4j: Setting property [append] to [true].
> > log4j: Setting property [file] to [server/log/server.log].
> > log4j: Setting property [datePattern] to ['.'yyyy-MM-dd].
> > log4j: setFile called: server/log/server.log, true
> > log4j: setFile ended
> > log4j: Appender [Default] to be rolled at midnight.
> > log4j: Parsed "Default" options.
> > log4j: Parsing appender named "Console".
> > log4j: Parsing layout options for "Console".
> > log4j: Setting property [conversionPattern] to [%d [%t] %-5p %c - %m%n].
> > log4j: End of parsing for "Console".
> > log4j: Parsed "Console" options.
> > log4j: Finished configuring.
> > log4j: JIVS: Time taken to look up loggerRepository 368ms
> >
> > I then deploy my service and call Logger.getLogger(my.service.class) to
> get
> > the following for the root logger with 2 appenders(A1 and A2):
> >
> > log4j: Parsing for [root] with value=[DEBUG, A1, A2].
> > log4j: Level token is [DEBUG].
> > log4j: Category root set to DEBUG
> > log4j: Parsing appender named "A1".
> > log4j: Parsing layout options for "A1".
> > log4j: Setting property [conversionPattern] to [%d [%t] %-5p %c - %m%n].
> > log4j: End of parsing for "A1".
> > log4j: Setting property [file] to [server/log/recorder.log].
> > log4j: Setting property [append] to [true].
> > log4j: Setting property [datePattern] to ['.'yyyy-MM-dd].
> > log4j: setFile called: server/log/recorder.log, true
> > log4j: setFile ended
> > log4j: Appender [A1] to be rolled at midnight.
> > log4j: Parsed "A1" options.
> > log4j: Parsing appender named "A2".
> > log4j: Parsing layout options for "A2".
> > log4j: Setting property [conversionPattern] to [%d [%t] %-5p %c - %m%n].
> > log4j: End of parsing for "A2".
> > log4j: Parsed "A2" options.
> > log4j: Finished configuring.
> > log4j: JIVS: Time taken to look up loggerRepository 33ms
> >
> > Now the problem:
> >
> > All my logs are directed to server.log and the console.  The
recorder.log
> > (log for the deployed service) is created, but no logs are appended to
the
> > file.  I know the log4j.properties config file of the service is found
and
> > loaded correctly due to the debug statements.
> >
> > I really need some direction here and have come to a dead end.  Your
> > feedback would be really appreciated.
> >
> > Cheers,
> > Vance
> >
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: [EMAIL PROTECTED]
> > For additional commands, e-mail: [EMAIL PROTECTED]
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to