Jess Holle wrote:

Remy Maucherat wrote:

BTW, JBoss (supposedly, I didn't check personally) uses commons-logging everywhere, and the logging implementation used is log4j.

That works since *everything* uses log4j. The issue is with Tomcat is really one of *not* having log4j at the Tomcat level but having it in your web app. This leads to:


   * whole crop of loggers using java.util.logging (fine, to be
     expected, and there are Java 5 MBeans -- albeit limited -- to
     interact with these)
   * a few core Tomcat loggers that are *not* by nature per web app
     loggers using the log4j jar and configuration of the first web app
     that uses the class enclosing them (e.g. the first web app to get
     a request!)
   * the web app's own classes using whatever you specify

It is the 2nd of these 3 bullet that is so disturbing to me. I'd like to see these either have separate loggers for each web app, or behave like the rest the Tomcat loggers and cause a leak of data and references between web apps. This -- and a reasonable set of MBeans to control/expose loggers seems quite doable with the approach Yoav and Bill laid out. It's just unfortunate that the out-of-the-box behavior with web apps using log4j is so onerous.

The core loggers you talk about are probably the ones used for reporting your servlets/filters/etc loading errors. This seems webapp related to me.

Considering the classes containing these loggers are not per web app as best I can tell I don't believe the loggers are, but I guess more thorough debugging on my part is in order. Perhaps I am mistaken and these are Tomcat loggers, but are specific to my web app.

Okay, I did a bit more digging.

*If*:

   * Your web app contains log4j.jar *and* commons-logging.jar.
   * You do not have log4j installed in any of Tomcat's own lib
     directories.
   * You use a JNDI or other contextual classloader based
     LogRepositorySelector.

*Then*:

   * The first Tomcat web application will "steal" loggers from the
     Tomcat base, i.e. any that happen to be obtained while the first
     web app's contextual classloader is active.
         o In a brief, simple test, whichever web app receives the
           first JSP page request will "steal" the following Tomcat
           loggers:
               + org.apache.jasper.compiler.Compiler
               + org.apache.jasper.compiler.JspReader
               + org.apache.jasper.runtime.PageContextImpl
               + org.apache.jasper.servlet.JspServletWrapper
               + org.apache.jasper.xmlparser.ParserUtils
   * By "steal", I mean that these loggers end up in the
     LoggerRepository of the given web app. Their configuration is thus
     controlled by it.  Also, they use the log4j library from the given
     web app.

I could always be mistaken, but my examination of the LoggerRepository's involved seems pretty conclusive.

If one has to have log4j and commons-logging in one's web app, then the only solution appears to be to put log4j in Tomcat and use a non-contextual classloader based LogRepositorySelector. Avoiding the contextual classloader based LogRepositorySelector only keeps Tomcats loggers from sharing the web app's intended LoggerRepository -- they still use the web app's log4j and its default LoggerRepository.

--
Jess Holle



Reply via email to