LogConfigurationException: No suitable Log constructor 

Displaying notes 1 - 2 of 2

Joined:
04/09/2007
Posts:
727

August 15, 2007 18:08:34    Last update: November 08, 2007 22:00:01
I had this problem when deploying a J2EE application into Oracle app server. It worked fine with an OC4J container configured in the default group. But it failed to start with an OC4J container I created. Here's a sample stack trace of the initialization exception:

07/08/14 13:32:46.34 10.1.3.3.0 Started
07/08/14 13:32:51.887 springapp: Error initializing servlet
java.lang.ExceptionInInitializerError
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:242)
	at com.evermind.server.http.HttpApplication.loadServlet(HttpApplication.java:2313)
	at com.evermind.server.http.HttpApplication.findServlet(HttpApplication.java:4824)
        .
        .
        ... lines omitted...
        .
Caused by: org.apache.commons.logging.LogConfigurationException: 
org.apache.commons.logging.LogConfigurationException: No suitable Log constructor 
[Ljava.lang.Class;@a05e2e for org.apache.commons.logging.impl.Log4JLogger (Caused by 
java.lang.NoClassDefFoundError: org/apache/log4j/Category) (Caused by 
org.apache.commons.logging.LogConfigurationException: No suitable Log constructor 
[Ljava.lang.Class;@a05e2e for org.apache.commons.logging.impl.Log4JLogger (Caused by 
java.lang.NoClassDefFoundError: org/apache/log4j/Category))
	at 
org.apache.commons.logging.impl.LogFactoryImpl.newInstance(LogFactoryImpl.java:543)
	at 
org.apache.commons.logging.impl.LogFactoryImpl.getInstance(LogFactoryImpl.java:235)
	at 
org.apache.commons.logging.impl.LogFactoryImpl.getInstance(LogFactoryImpl.java:209)
	at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:351)
	at org.apache.struts.action.ActionServlet.<clinit>(ActionServlet.java:226)
	... 22 more


The problem was, the struts ActionServlet loads commons logging LogFactory, the log factory somehow knows that it needs log4j, but it can't load log4j since it's loaded by a different class loader. The solution for Oracle is to omit commons logging from the list of inherited libraries. Add this to META-INF/orion-application.xml solves the problem:

<imported-shared-libraries>
       <remove-inherited name="apache.commons.logging"></remove-inherited>
</imported-shared-libraries>


Actually, this is a quite common problem with commons-logging. If you search the web, you'll find that people have been fighting this problem for years in various environments including Tomcat, Jetty, Eclipse, Hibernate etc. Is this an inherent problem in the design of commons logging or just that people aren't using it correctly?
Share |
| Comment  | Tags
2 comments  
Easy email testing with http://www.ximailstop.com
Joined:
04/09/2007
Posts:
727

May 19, 2008 16:03:25    Last update: May 19, 2008 16:03:25
Actually this is a problem with commons logging. A detailed analysis is presented by Ceki Gülcü, the creator of log4j.

In short, the problem appears when commons logging (shorthanded as JCL following Ceki Gülcü) is loaded by a parent class loader but log4j is loaded by a child class loader. But how come JCL finds log4j in one place but fails to instantiate it following its discovery? It turned out that JCL does the discovery with one class loader (the thread context class loader) but the instantiation with a different class loader (the class loader that loaded JCL).

Therefore, the workaround is either to exclude JCL from the class loader delegation chain (as shown above for OC4J), or make log4j available to the parent class loader.
Share |
| Comment  | Tags
 
Easy email testing with http://www.ximailstop.com