commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Ollie" <>
Subject Re: Log4JLogger does not implement Log
Date Sat, 21 May 2005 01:06:48 GMT
Oh, for sure knowledge is power and I have more now, thanks. I use tomcat's common/lib, /shared/lib/
and WEB-INF/lib/ classloaders already for the shared behaior of registries, etc.  This is
the first time I have run into this problem, so I didn't understand. 

Good point on the external.classpath and classpath elements, I will investigate. 

It should however be a little less complicated than you describe because the problem ONLY
occurs running the ant task under that one target and not on startup of the tomcat webapp.
I can also run that build outside eclipse and this error does NOT occur so it is in the ant
in eclipse environment. 


-----Original Message-----
From: Simon Kitching <>
Date: Sat, 21 May 2005 12:15:18
Subject: RE: Log4JLogger does not implement Log

On Fri, 2005-05-20 at 15:55 -0700, Michael Oliver wrote:
> Well ok, I understand more now, thanks.  However, if from what you say
> the commons-logging.jar MUST be shared, and therefore in the ant runtime
> global entries, and NOT in the classpath of the ant task, then why is it
> when it isn't in the ant runtime global entries, but is in the task
> classpath I get a NoClassDefFound error?

The question is what is in ${classpath.external} and ${classpath}.

I bet there is some "shared" library there that contains a class that
one of the com.alarius classes calls, and that the "shared" class uses
commons-logging. Because that class is loaded via the shared
classloader, by the normal classloader rules LogFactory must be
available via that classloader too. Removing commons-logging.jar from
the shared classpath therefore results in NoClassDefFound.

If you remove ${classpath.external} and ${classpath} from your
compile.classpath completely, then what missing classes are reported? I
bet one of them uses commons-logging...

That's why an alternative solution to your problem is to figure out what
that class is, and ensure it is deployed in WEB-INF/lib not (or in
addition to) via the shared classloader. Actually, this is a nicer
solution but it can be tricky to figure out what the problem classes
are, which is why I suggested the simpler solution of removing logging
from the child classloader instead.

> I don't see how it can be both ways, either two are loading and the
> abstract class is loading before the concrete class and throwing the
> subject error or not.

It's nothing to do with the order that the classes get loaded.

It's the fact that class X@sharedLoader uses LogFactory@sharedLoader
which uses Log@sharedLoader. Class Y@childLoader then calls
X@sharedLoader with the context classloader set to childLoader, and
X@sharedLoader calls LogFactory.getLogger. So LogFactory@sharedLoader
looks in the context classloader (childLoader) for an adapter, and finds
Log4JLogger@childLoader. But that class actually implements
Log@childLoader, and therefore cannot be cast to Log@sharedLoader.

Are you sure you really wanted the full explanation? :-)

The reason that LogFactory tries to load the Log4JLogger via the context
classloader is so that when commons-logging.jar is deployed via a shared
loader, the actual logging library can still be deployed via the child
classloader (ie in WEB-INF/lib). In particular, tomcat does this. And it
works well. However it fails badly in the one situation I described
earlier, and which you have struck: that *ALL* of the below are true:
 * child-first classloading order selected in child classloader
 * code in child classloader that calls JCL
 * commons-logging.jar available via child classloader
 * code in shared classloader that calls JCL
 * commons-logging.jar available via shared classloader

Hopefully commons-logging 1.0.5 will have a fix for this; work is in
progress at the moment. But for now, you just need to ensure that you do
something that breaks the problem setup, by making *one* of the above
items false. Removing commons-logging from WEB-INF/lib is the easiest
(though not necessarily the best) fix.

> This is running in eclipse during an ant build, not in Tomcat or
> someplace else, so I am unsure of shared class loader, child class
> loader or where/how to set or change the child first or parent first
> setting.  So your words do not carry the desired meaning within my
> understanding.

Yes, it's an extremely complicated classloader setup you have, with
eclipse, ant and tomcat all involved. That's why I phrased my response
in terms of a normal situation where a servlet container such as tomcat
is running a webapp - I know how things work in that situation and I'm
sure the same principles apply. However you'll have to figure out
exactly how those principles fit into your very complicated setup. Or
figure out how to simplify your setup, eg configure eclipse to do the
compilation with an external compiler or run ant with the "fork"



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

Mike Oliver
CTO, Alarius Systems LLC
Las Vegas, Nevada USA

Sent using my BlackBerry 6510 from Nextel

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

View raw message