Log4JLogger does not implement Log

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Log4JLogger does not implement Log

Michael Oliver
I have created an ant task as follows:

 

<path id="compile.classpath">

    <pathelement path ="${webinf.dir}/lib/commons-beanutils.jar"/>

    <pathelement path ="${webinf.dir}/lib/commons-digester.jar"/>

    <pathelement path ="${webinf.dir}/lib/commons-logging.jar"/>

    <pathelement path ="${webinf.dir}/lib/AJContentClient.jar"/>

    <pathelement path ="${webinf.dir}/lib/AJRegistries.jar"/>

    <pathelement path ="${webinf.dir}/lib/AlariusESB.jar"/>

    <pathelement path ="${webinf.dir}/lib/log4j-1.2.8.jar"/>

    <pathelement path ="${webinf.dir}/lib/junit.jar"/>

    <pathelement path ="${webinf.dir}/lib/struts.jar"/>

    <pathelement path = "${webinf.dir}/lib/standard.jar"/>

    <pathelement path ="${webinf.dir}/classes"/>

    <pathelement path ="${classpath.external}"/>

    <pathelement path ="${classpath}"/>

</path>

 

<target name="axis-java2wsdl">

<echo message="Building wsdl for ${project.distname} at
${local.wsdl}}"/>

     

  <axis-java2wsdl

 
classname="com.alarius.assignments.actions.SaveAssignmentForm"

      style= "DOCUMENT"

      namespace= "urn:http://alariussystemsllc.com/AJCCWebService/"

      location= "http://localhost:8080/AlariusAssignments/services/"

      output="AlariusAssignments.wsdl" >

      <classpath>

            <pathelement path ="${webinf.dir}/classes"/>

      </classpath>

      <classpath refid="compile.classpath"/>

                       

  </axis-java2wsdl >

</target>

 

commons-logging and log4j are in the compile.classpath

 

When I run this target I get

 

axis-java2wsdl:

     [echo] Building wsdl for AlariusAssignments at
C:\Java\ArchivedWorkspaces\AlariusAssignments\AlariusAssignments.wsdl}

[axis-java2wsdl] Java2WSDL
com.alarius.assignments.actions.SaveAssignmentForm

[axis-java2wsdl] java.lang.ExceptionInInitializerError

[axis-java2wsdl] at java.lang.Class.forName0(Native Method)

...

[axis-java2wsdl] Caused by:
org.apache.commons.logging.LogConfigurationException:
org.apache.commons.logging.LogConfigurationException:
org.apache.commons.logging.LogConfigurationException: Class
org.apache.commons.logging.impl.Log4JLogger does not implement Log

[axis-java2wsdl] at
org.apache.commons.logging.impl.LogFactoryImpl.newInstance(LogFactoryImp
l.java:532)...

 

So researching this I find that the "Log4JLogger does not implement Log"
is caused by a classloader problem.

 

So I found in the eclipse ant runtime preferences Global Entries, both
the commons-logging and log4j jars.  So I removed them from there and
ran ant on that target again...

 

axis-java2wsdl:

     [echo] Building wsdl for AlariusAssignments at
C:\Java\ArchivedWorkspaces\AlariusAssignments\AlariusAssignments.wsdl}

[axis-java2wsdl] java.lang.NoClassDefFoundError:
org.apache.commons.logging.LogFactory

[axis-java2wsdl] at
org.apache.axis.components.logger.LogFactory.class$(LogFactory.java:84)

...

 

Huh???

 

If the ant runtime is loading the commons-logging and log4j jars and
that causes a classloader sequence problem, then removing them from
there and leaving the ones in the compile.classpath should NOT cause a
NoClassDefFoundError.

 

How can it be that one way it doesn't find LogFactory and the other way
it has a classloader sequence problem?

 

Conversely if ant needs to load them and the ant axis task also needs to
load them, how do I ensure they are loaded in the proper sequence to
avoid the conflict?

 

Michael Oliver

CTO

Alarius Systems LLC

6800 E. Lake Mead Blvd, #1096

Las Vegas, NV 89156

Phone:(702)643-7425

Fax:(702)974-0341

*Note new email changed from [hidden email]

 

 

 

 

Reply | Threaded
Open this post in threaded view
|

Re: Log4JLogger does not implement Log

Simon Kitching
On Fri, 2005-05-20 at 10:49 -0700, Michael Oliver wrote:

> When I run this target I get
>
>  
>
> [axis-java2wsdl] Caused by:
> org.apache.commons.logging.LogConfigurationException:
> org.apache.commons.logging.LogConfigurationException:
> org.apache.commons.logging.LogConfigurationException: Class
> org.apache.commons.logging.impl.Log4JLogger does not implement Log
>
> [axis-java2wsdl] at
> org.apache.commons.logging.impl.LogFactoryImpl.newInstance(LogFactoryImp
> l.java:532)...
>
>  
>
> So researching this I find that the "Log4JLogger does not implement Log"
> is caused by a classloader problem.
>
>  
>
> So I found in the eclipse ant runtime preferences Global Entries, both
> the commons-logging and log4j jars.  So I removed them from there and
> ran ant on that target again...
>
>  
>
> axis-java2wsdl:
>
>      [echo] Building wsdl for AlariusAssignments at
> C:\Java\ArchivedWorkspaces\AlariusAssignments\AlariusAssignments.wsdl}
>
> [axis-java2wsdl] java.lang.NoClassDefFoundError:
> org.apache.commons.logging.LogFactory
>
> [axis-java2wsdl] at
> org.apache.axis.components.logger.LogFactory.class$(LogFactory.java:84)
>
> ...
>
>  
>
> Huh???
>
>  
>
> If the ant runtime is loading the commons-logging and log4j jars and
> that causes a classloader sequence problem, then removing them from
> there and leaving the ones in the compile.classpath should NOT cause a
> NoClassDefFoundError.
>
>  
>
> How can it be that one way it doesn't find LogFactory and the other way
> it has a classloader sequence problem?

This problem is caused when you have *all* of the following 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

Because you have code in the shared classloader that calls JCL, you
*must* deploy commons-logging.jar at the shared level.

So the simplest fix is to delete the commons-logging.jar from the child
classloader. The downside of this is that all your logging config then
becomes "global", ie you need to configure logging using a config file
at the shared level, and webapps share the same logging instance. But I
don't think you really care about logging in this case do you?


Regards,

Simon


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

RE: Log4JLogger does not implement Log

Simon Kitching
In reply to this post by Michael Oliver
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"
option....

Regards,

Simon



---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Log4JLogger does not implement Log

Ollie-13
In reply to this post by Michael Oliver
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.

Ollie

-----Original Message-----
From: Simon Kitching <[hidden email]>
Date: Sat, 21 May 2005 12:15:18
To:[hidden email]
Cc:[hidden email]
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"
option....

Regards,

Simon



---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]


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

Sent using my BlackBerry 6510 from Nextel

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Log4JLogger does not implement Log

Mattias Jiderhamn-2
In reply to this post by Michael Oliver
At 2005-05-20 19:49, you wrote:

>...
>   <axis-java2wsdl
>
>
>classname="com.alarius.assignments.actions.SaveAssignmentForm"
>
>       style= "DOCUMENT"
>
>       namespace= "urn:http://alariussystemsllc.com/AJCCWebService/"
>
>       location= "http://localhost:8080/AlariusAssignments/services/"
>
>       output="AlariusAssignments.wsdl" >
>
>       <classpath>
>
>             <pathelement path ="${webinf.dir}/classes"/>
>
>       </classpath>
>
>       <classpath refid="compile.classpath"/>
>
>   </axis-java2wsdl >
>
></target>
>
>...
>
>[axis-java2wsdl] Caused by:
>org.apache.commons.logging.LogConfigurationException:
>org.apache.commons.logging.LogConfigurationException:
>org.apache.commons.logging.LogConfigurationException: Class
>org.apache.commons.logging.impl.Log4JLogger does not implement Log

This is why lots of people hate Commons Logging (see
http://www.qos.ch/logging/classloader.jsp and
http://www.qos.ch/logging/thinkAgain.jsp).

Without knowing the details of your classpath, using fork migh help. Don't
remember whether there is a fork-attribute on the axis-java2wsdl task; if
not try an ordinary "java" task with fork.

   / Mattias J


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

RE: Log4JLogger does not implement Log

Michael Oliver
Thanks, will try the <java> task with fork and let the list know.

Michael Oliver
CTO
Alarius Systems LLC
6800 E. Lake Mead Blvd, #1096
Las Vegas, NV 89156
Phone:(702)643-7425
Fax:(702)974-0341
*Note new email changed from [hidden email]

-----Original Message-----
From: Mattias J [mailto:[hidden email]]
Sent: Saturday, May 21, 2005 12:37 AM
To: Jakarta Commons Users List
Subject: Re: Log4JLogger does not implement Log

At 2005-05-20 19:49, you wrote:

>...
>   <axis-java2wsdl
>
>
>classname="com.alarius.assignments.actions.SaveAssignmentForm"
>
>       style= "DOCUMENT"
>
>       namespace= "urn:http://alariussystemsllc.com/AJCCWebService/"
>
>       location= "http://localhost:8080/AlariusAssignments/services/"
>
>       output="AlariusAssignments.wsdl" >
>
>       <classpath>
>
>             <pathelement path ="${webinf.dir}/classes"/>
>
>       </classpath>
>
>       <classpath refid="compile.classpath"/>
>
>   </axis-java2wsdl >
>
></target>
>
>...
>
>[axis-java2wsdl] Caused by:
>org.apache.commons.logging.LogConfigurationException:
>org.apache.commons.logging.LogConfigurationException:
>org.apache.commons.logging.LogConfigurationException: Class
>org.apache.commons.logging.impl.Log4JLogger does not implement Log

This is why lots of people hate Commons Logging (see
http://www.qos.ch/logging/classloader.jsp and
http://www.qos.ch/logging/thinkAgain.jsp).

Without knowing the details of your classpath, using fork migh help.
Don't
remember whether there is a fork-attribute on the axis-java2wsdl task;
if
not try an ordinary "java" task with fork.

   / Mattias J


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]



---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]