On Wed, 2005-05-18 at 12:20 +0200, David Perez wrote:
> You're right, I have changed the commons-logging version to the latest one.
> Now I have reverted to commons-logging-1.0.2

I would recommend using commons-logging-1.0.4. After all, that is the
most recent official release.


> >I suggest registering a ServletContextListener. Declare a <listener>
> >element in the web.xml file, with a nested <listener-class> element
> >containing the fully qualified classname of a logging-cleanup class. In
> >the contextDestroyed method of that class do this:
> > * LogFactory.release(
> >     Thread.currentThread().getContextClassLoader())
> > * somehow cleaning up the underlying logging library if needed.
> >
> >If that doesn't help, let me know and we can look into it a bit
> >further. 
> >  
> >
>  From my code I call LogFactory.releaseAll() after removing the old web 
> app context, and no luck :-(

Do you mean that you use a ServletContextListener as I described? Or
something else?

Note also that LogFactory.releaseAll may not do what you want. If your
webapp has bound to commons-logging that is loaded via a shared
classloader, then calling releaseAll will shut down *all* instances of
commons-logging - which other webapps running in the same container may
not appreciate :-). The code I recommended will only shut down logging
for the webapp whose context is being destroyed, assuming you are
calling the method from a SerletContextListener.contextDestroyed, ie
from code where Thread.currentThread.getContextClassLoader() returns the
classloader of the webapp being unloaded.

> Should my webapp use another copy of commons-logging.jar?

That depends.

If your webapp has all the libraries it needs in WEB-INF/lib, then yes.
Deploying commons-logging.jar in WEB-INF/lib in that situation makes
things very clean and consistent. There's no need to use call
LogFactory.release() in this case, as undeploying the webapp
automatically undeploys commons-logging and the underlying logging lib.

But if your webapp is calling into code that is deployed via a shared
classloader, and that code uses commons-logging, then you must *not*
also deploy commons-logging in WEB-INF/lib. If you do (and you are using
release 1.0.4), you will get the message
  Invalid class loader hierarchy.  
  You have more than one version of org.apache.commons.logging.Log
  visible, which is not allowed.
If you are using an earlier release, you will probably get something
like:
  AvalonLogger does not implement Log



> Here is the logging jars I use in my app:
> 
> jars used by the web server (Jetty):
> 
>     * commons-logging.jar and
>     * log4j.jar
> 
> jars used by the webapp:
> 
>     *    logkit.jar
> 
>     My web app uses Cocoon which uses Avalon LogKit, and makes me 
> include logkit.jar, even though logging is redirected to log4j. 

What do you mean "logging is redirected to log4j"?

>     Some other classes use directly commons-logging
> 
> With commons-logging-1.0.4 and 1.05 alpha1, I have to make logkit.jar 
> available to Jetty, otherwise commons-loggings throws a 
> ClassNotFoundException, because it cannot find
> 
> org/apache/log/Hierarchy.  I wonder why it tries to load LogKit if Log4j is 
> already available?

Commons-logging does *not* auto-discover LogKit; it doesn't even try. So
somewhere something in your webapp must be *ordering* commons-logging to
use AvalonLogger (aka LogKit) as the logger. 

Which logging lib commons-logging uses can be explicitly set via a
number of methods; .properties files, jdk1.3 service files, system
properties. See the commons-logging documentation for more information.


> Caused by: java.lang.NoClassDefFoundError: org/apache/log/Hierarchy
>       at 
> org.apache.commons.logging.impl.LogKitLogger.getLogger(LogKitLogger.java:77)
>       at 
> org.apache.commons.logging.impl.LogKitLogger.<init>(LogKitLogger.java:64)
>       at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
>       at 
> sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
>       at 
> sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
>       at java.lang.reflect.Constructor.newInstance(Constructor.java:494)
>       at 
> org.apache.commons.logging.impl.LogFactoryImpl.newInstance(LogFactoryImpl.java:529)

Yep, commons-logging's LogFactoryImpl is explicitly trying to
instantiate a LogKitLogger object. 



Can you please:
(a) look for what is ordering commons-logging to use LogKit and remove
that?
(b) use commons-logging 1.0.4; I will be able to help you much better
than if you use the very old 1.0.2. 

Also, can you please confirm that Jetty (and your webapp) use the
standard child-first (aka parent-last) classloading order? I know the
Resin webserver doesn't, and that makes things quite different...


And by the way, where do you put your log4j configuration file? 



Good luck!

Simon


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

Reply via email to