commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Simon Kitching <>
Subject Re: [logging] diagnostics, RC failure in webapp
Date Mon, 17 Apr 2006 08:48:54 GMT
On Mon, 2006-04-17 at 00:32 +1200, Simon Kitching wrote: 
> Hi,
> I've been able to reproduce the logging problem I reported earlier with
> very little trouble. However I am unable to figure out *why* it's
> failing.
> To summarise: Class Log4JLogger is being loaded from a classloader; that
> classloader can see file "Log4JLogger.class" fine as a resource.
> Log4JLogge depends on org.apache.log4j.Category, but that is also
> visible from the classloader. Yet Log4JLogger gets NoClassDefFound when
> loaded. Very puzzling.

Ok, I've made some progress. The problem is that Tomcat's
WebappClassLoader is doing some non-standard stuff.

In WebappClassLoader.loadClass, it tries:
   // (0) Check our previously loaded local class cache

   // (0.1) Check our previously loaded class cache

   // (0.2) Try loading the class with the system class loader, to prevent
   //       the webapp from overriding J2SE classes

   // do normal lookup stuff if class not found in system classloader

The problem is step (0.2). Tomcat's startup process puts very few jars
in the system classpath. Its bootup code then creates a classloader that
just about everything related to tomcat gets loaded into. Unfortunately
one of the things that *does* go into the system classpath is ..

The result is that WebappClassLoader prevents any webapp from providing
its own implementation of any class in the jarfile

This behaviour of Tomcat isn't a problem as long as the
commons-logging-api.jar really is an api jarfile, without any adapters
that depend on external concrete logging libraries. In fact, it's good,
as the Log class can be duplicated in the classpath without harm; the
one in ${tomcat.home}/bin/commons-logging-api.jar will be used always. 

However it does mean that jar ${tomcat.home}/bin/commons-logging-api.jar
must *never* include any adapters (eg Log4JLogger) which depends on an
external lib, as the adapter class will always be loaded via the system
classloader and therefore will be unable to see the concrete library.
That's what I did wrong; replace the api jar with the full jar. Note
that Jdk14Logger is not a problem, as it doesn't depend on any libs
deployed in the webapp.

I've checked the tomcat source; this advice applies to the entire 5.5.x
series, 5.0.x series, and 4.1.x series. The 4.0.x series is different;
it only uses the system classloader for classes in the "java.*"

Tomcat's behaviour does mean that when a webapp deploys commons-logging
1.1 in its WEB-INF/lib, it won't actually be using any of the new
LogFactory/LogFactoryImpl stuff, as tomcat's version of JCL will
override it. 

Hmm..wonder what happens if the 1.1 logging adapter classes are loaded
by a JCL 1.0.4 LogFactoryImpl. That's what will end up happening in this


There isn't really anything wrong with the current RC8 code, except for
the diagnostic message "Foo unusable; did you mean Foo?", and the docs. 

(Well, there was one bug I spotted by coincidence, where priority field
in first file was ignored; that's been

I'll update JCL docs to say that tomcat's
${tomcat.home}/bin/commons-logging-api.jar must never be replaced with a
"full" jarfile.

I'm also planning to fix the minor diagnostic message issue in the next
hour or so.

And we should probably double-check behaviour of 1.1 adapter classes
when loaded by an old JCL version.



To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message