Environment:
 
commons-logging-1.0.2.jar
log4j-1.2.6.jar
Apache Tomcat/4.1.12-LE-jdk14
 
Situation:
 
I have my own realm implementation that is stable in Tomcat 4.0.3-LE, 
and I'm moving up to 4.1.12.  In addition, I am also moving all of my 
codebase to the commons-logging package.  After moving to 
commons-logging, everything in my codebase works in a simple JVM, i.e. 
JUnit tests and Java Applications.  When this is inside the tomcat 
classloader heirarchy though, NOTHING works. Each of the following 
scenarios describe the things I've done, with somewhat different 
results, but all leading back to incompatible class loading schemes.  Is 
there a tomcat bug?  The first scenario describes a situation where a 
server realm component is finding the log4j classes using the method 
from the LogFactoryImpl.isLog4JAvailable() method...it returns 'true' 
when the log4j classes ARE NOT in the server/lib, but all the way down 
in one of my  webapp/lib.  I believe this is a tomcat issue.
 
==============================================
This scenario is debug output I placed in the methods that the 
LogFactory uses to determine if log4j is available. I copied 
loadClass(), isLog4JAvailable(), getContextClassLoader() from the 
LogFactory and LogFactoryImpl into my Realm, and here is the output when 
I put log4j.jar in my 'operations' webapp
and made sure that the log4j.jar is not available anywhere else in the 
tomcat heirarchy:
 
->loadClass(org.apache.log4j.Category)
->trying the context classloader from Thread.getContextClassLoader()
->got the context classloader from Thread.getContextClassLoader()
->contextClassLoader worked.  returning class org.apache.log4j.Category
->trying Class.forName(org.apache.log4j.Category)
->Class.forName RETURNING an exception.
****isLog4JAvailable(): true
 
This should be false!  Why should a server component be able to access 
my webapp's jars???  Is the commons-logging package unsafely assuming 
how a classloader will work, or is the Tomcat-Catalina configuration of 
tiered classloaders incorrectly allowing access to that class via the 
thread context classLoader?  Nonetheless, even if the tomcat class 
loader isn't doing it's job exactly, the commons-logging package tests 
for that class via the contextClassLoader, but  it then cannot 
instantiate the class.  That would mean that it's not using the context 
class loader to instantiate...wouldn't it?  If so, that is inconsistent 
as well.


==============================================
When I put the log4j-1.2.6.jar in with the latest
commons-logging-1.0.2.jar in catalina\server\lib:
 
Using CATALINA_BASE:   ..
Using CATALINA_HOME:   ..
Using CATALINA_TMPDIR: ..\temp
Using JAVA_HOME:       C:\Development\lib\jdk\j2sdk1.4.0
Exception during startup processing
java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.jav
a:39)
        at 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessor
Impl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:324)
        at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:203)
Caused by: java.lang.NoClassDefFoundError: org/apache/log4j/Layout
        at 
org.apache.commons.logging.impl.Log4jFactory.getInstance(Log4jFactory.ja
va:153)
        at 
org.apache.commons.logging.impl.LogFactoryImpl.getInstance(LogFactoryImp
l.java:285)
        at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:409)
        at org.apache.commons.digester.Digester.<init>(Digester.java:281)
        at 
org.apache.catalina.startup.Catalina.createStartDigester(Catalina.java:2
80)
        at org.apache.catalina.startup.Catalina.start(Catalina.java:441)
        at org.apache.catalina.startup.Catalina.execute(Catalina.java:400)
        at org.apache.catalina.startup.Catalina.process(Catalina.java:180)
        ... 5 more
==============================================
 
 
==============================================
When I have NO log4j-1.2.6.jar (anywhere in the catalina heirarchy), The
tomcat system will startup, but when
I execute the Realm (via a request), i get this:
 
java.lang.ExceptionInInitializerError
        at
com.iverticalleap.security.module.tomcat.Realm.authenticate(Realm.java:1
51)
        at
org.apache.catalina.authenticator.FormAuthenticator.authenticate(FormAut
henticator.java:263)
        at
org.apache.catalina.authenticator.AuthenticatorBase.invoke(Authenticator
Base.java:458)
        at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.i
nvokeNext(StandardPipeline.java:641)
        at
org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:4
80)
        at
org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
        at
org.apache.catalina.core.StandardContext.invoke(StandardContext.java:239
6)
        at
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java
:180)
        at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.i
nvokeNext(StandardPipeline.java:643)
        at
org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherVa
lve.java:170)
        at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.i
nvokeNext(StandardPipeline.java:641)
        at
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java
:172)
        at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.i
nvokeNext(StandardPipeline.java:641)
        at
org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:4
80)
        at
org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
        at
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.
java:174)
        at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.i
nvokeNext(StandardPipeline.java:643)
        at
org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:4
80)
        at
org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
        at
org.apache.coyote.tomcat4.CoyoteAdapter.service(CoyoteAdapter.java:223)
        at
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:40
5)
        at
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processC
onnection(Http11Protocol.java:380)
        at
org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:50
8)
        at
org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool
.java:533)
        at java.lang.Thread.run(Thread.java:536)
Caused by: org.apache.commons.logging.LogConfigurationException:
org.apache.commons.logging.LogConfigurationException: o
rg.apache.commons.logging.LogConfigurationException: Class
org.apache.commons.logging.impl.Jdk14Logger does not implemen
t Log
        at
org.apache.commons.logging.impl.LogFactoryImpl.newInstance(LogFactoryImp
l.java:555)
        at
org.apache.commons.logging.impl.LogFactoryImpl.getInstance(LogFactoryImp
l.java:289)
        at
org.apache.commons.logging.impl.LogFactoryImpl.getInstance(LogFactoryImp
l.java:259)
        at
org.apache.commons.logging.LogFactory.getLog(LogFactory.java:390)
        at
com.iverticalleap.util.logging.AbstractLoggable.getLog(AbstractLoggable.
java:28)
        at
com.iverticalleap.util.logging.AbstractLoggable.logDebug(AbstractLoggabl
e.java:189)
        at
com.iverticalleap.util.pool.AbstractBroker.<init>(AbstractBroker.java:39
)
        at
com.iverticalleap.util.pool.AbstractBroker.<init>(AbstractBroker.java:44
)
        at
com.iverticalleap.service.ServiceBroker.<init>(ServiceBroker.java:27)
        at
com.iverticalleap.service.ServiceBroker.<clinit>(ServiceBroker.java:23)
        ... 25 more
Caused by: org.apache.commons.logging.LogConfigurationException:
org.apache.commons.logging.LogConfigurationException: C
lass org.apache.commons.logging.impl.Jdk14Logger does not implement Log
        at
org.apache.commons.logging.impl.LogFactoryImpl.getLogConstructor(LogFact
oryImpl.java:420)
        at
org.apache.commons.logging.impl.LogFactoryImpl.newInstance(LogFactoryImp
l.java:548)
        ... 34 more
Caused by: org.apache.commons.logging.LogConfigurationException: Class
org.apache.commons.logging.impl.Jdk14Logger does
not implement Log
        at
org.apache.commons.logging.impl.LogFactoryImpl.getLogConstructor(LogFact
oryImpl.java:416)
        ... 35 more
 
 
With log4j in the server/lib dir, I get a similar message stating
"Log4JCategoryLog does not implement Log"
==============================================
 
 
 
In conclusion, I've spent a great deal of time looking into this, and I
believe it may be a manifestation of a
combination of problems.  I may be able to help figure this out if the
following questions can be answered:
 
 >From the commons-logging developers:  ----
Why is the class loading done this way? 
Is it necessary? 
Why are both the JDK14 and log4j loggers failing to test as
assignableFrom(Log) in the catalina server-side (not webapp-side)
runtime environment?
 
 >From the catalina developers:  ----
Why can a server component (Realm) find a class from a webapp's lib
directory via the
Thread.currentThread().getContextClassLoader().loadClass() without a
ClassNotFoundException? 
I'm not even sure this is possible, but if catalina allows a class to be
loaded or even instantiated via a particular classloader (thread
context), but the typical classloader is used to determine
MyClassThatImplementsLogFromThreadContextClassLoader.assignableFrom(Log.
class), this would explain why nothing passes the implementation test in
the LogFactory.class.
 
 
 
Last conclusion, am I crazy? ;)  Any thoughts are welcome and we come to
a solution, I'll be glad to submit a patch.
 
 
-Kevin Ross




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

Reply via email to