commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Will Jaynes <>
Subject Re: commons-logging & classloading
Date Fri, 10 Oct 2003 19:31:25 GMT
Todd, I put c-l at the server and web app levels because that's how I 
could get it to work (and only with my changed version). I've tried 
*every* configuration of jar files and the *only* thing that works is if 
I put all jars into each WEB-INF/lib. Please remember that all was well 
with me until I tried putting HttpClient.jar (which uses 
commons-logging) at the server level. That's when I began experiencing 

Before I tried adding HttpClient.jar to the server level, I lived 
happily with commons-logging and log4j in each web app. Each web app had 
it's own and was independent of all other web apps. 
Life was good.


Todd Jonker wrote:

> Will, I'm curious: Why do you have commons-logging at both the server
> AND web-app levels?  It seems to me that if you only put it at the
> server level then all the apps will use the same logging framework.
> That's what I'm doing currently.
> .T.
>> -----Original Message----- From: Will Jaynes
>> [] Sent: Friday, October 10, 2003 04:59 PM 
>> To: 'Jakarta Commons Developers List' Subject: Re: commons-logging
>> & classloading
>> I was hoping some developers would weigh in on this issue. I expect
>> that this has been discussed before, but I can't find any
>> references.
>> I believe the classloading in commons-logging is broken. The web
>> app use case I describe below is a demonstration of why c-l is
>> broken. The way classloading is implemented makes it impossible to
>> to share components at the J2EE server level. It's clear from
>> looking at the LogFactory.getContextClassLoader() method that the
>> developers explicitly want to use the thread context classloader.
>> But it just causes problems.
>> I went in and changed LogFactory.getContextClassLoader() to simply
>>  return LogFactory.class.getClassLoader(), and all my logging
>> problems went away. I can put slide, HttpClient, commons-logging at
>> the server level; and struts, commons-logging, log4j in the web
>> apps. And things work fine and just as I expect them to.
>> So, can someone please explain why commons-logging is implemented
>> as it is? Will anyone consider changing it?
>> Thanks, Will
>> Will Jaynes wrote:
>>>>> Why does LogFactoryImpl in commons-logging try to load the
>>>>> Log implementation class first from thread classloader and
>>>>> then loader that loaded this class?
>>>>> Is there some kind of design pattern behind this?
>>>> One very common :-) use case for commons-logging is inside web 
>>>> applications, where the servlet container provides a class
>>>> loader per webapp (pointing at the classes in /WEB-INF/classes
>>>> and /WEB-INF/lib), plus normally a parent class loader for
>>>> shared classes and resources. The container is required to set
>>>> the Thead context class loader for the current webapp prior to
>>>> handing the request off to the servlet.
>>>> The lookup design pattern in LogFactoryImpl allows webapps to
>>>> use their own version of the log implementation classes.
>>> With regard to this web app use case, the problem I'm seeing is
>>> that I can't share components at the server level if they use
>>> commons-logging. What must the configuration of jars and property
>>> files look like if I have components that use commons-loggin both
>>> at the server and web app levels?
>>> So far, nothing works properly unless all components are at the
>>> web app level (in WEB-INF/lib).
>>> Here's an example of what can go wrong: I have slide and
>>> HttpClient in at the server level in resin/lib. HttpClient uses
>>> commons-logging, so I have to add commons-logging to resin/lib.
>>> My web app uses Struts, so I've got commons-logging in 
>>> WEB-INF/lib, and I use log4j, so log4j.jar is also in
>>> WEB-INF/lib. (by the way, I'm using Java 1.4)
>>> As soon as my web app trys to use HttpClient I get a exception :
>>> "Class org.apache.commons.logging.impl.Log4JLogger does not
>>> implement Log". I believe that what is happening is this:
>>> HttpClient loads with the server classloader. HttpClient wants to
>>> log, so it causes Log and LogFactory to be loaded with the server
>>> classloader. LogFactory specifically uses the thread context
>>> classloader to look a log factory. The thread context classloader
>>> is the web app's classloader, so it finds LogFactoryImpl and 
>>> log4j and then loads Log4JLogger, but it is still using the
>>> thread context classloader, so it finds the Log4JLogger in the
>>> WEB-INF/lib. It then does a check with
>>> Log.class.isAssignableFrom() on Log4JLogger, but since Log and
>>> Log4JLogger were loaded with different classloaders the test
>>> fails and the exception is thrown.
>>> After a lot of experimentation, the only configuration of jars
>>> that works properly is to put everything in the WEB-INF/lib of
>>> each web app. Commons-loggin has made it impossible to deploy
>>> slide and HttpClient at the server level.
>>> Am I missing something in how to configure this use case?
>>> Will
>>> ---------------------------------------------------------------------
>>>  To unsubscribe, e-mail:
>>> For additional
>>> commands, e-mail:
>> ---------------------------------------------------------------------
>>  To unsubscribe, e-mail:
>>  For additional commands, e-mail:
> ---------------------------------------------------------------------
>  To unsubscribe, e-mail: 
> For additional commands, e-mail:

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

View raw message