CTO of Tocea company, the (re) factory of tools for developers. Sylvain has posted 2 posts at DZone. You can read more from them at their website. View Full User Profile

Spring 3.1 Release and runtime exception with Logfactory

05.07.2012
| 3216 views |
  • submit to reddit

With the upgrade this morning of our applications to Spring 3.1.1-RELEASE, we obtained odd runtime exceptions :

The detailed stacktrace is : 

java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
	at org.springframework.context.support.AbstractApplicationContext.<init>(AbstractApplicationContext.java:161)
	at org.springframework.context.support.AbstractRefreshableApplicationContext.<init>(AbstractRefreshableApplicationContext.java:90)
	at org.springframework.context.support.AbstractRefreshableConfigApplicationContext.<init>(AbstractRefreshableConfigApplicationContext.java:59)
	at org.springframework.context.support.AbstractXmlApplicationContext.<init>(AbstractXmlApplicationContext.java:61)
	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:136)
	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
	at com.tocea.codewatch.platform.service.local.LocalCodewatch.init(LocalCodewatch.java:116)
	at com.tocea.codewatch.platform.service.local.LocalCodewatch.<init>(LocalCodewatch.java:50)
	at com.tocea.codewatch.platform.front.test.FakeAuditTest.setUp(FakeAuditTest.java:54)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:616)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory
	at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
	... 32 more

  The suspected class is

/**
...
*/
public abstract class AbstractApplicationContext extends DefaultResourceLoader
        implements ConfigurableApplicationContext, DisposableBean {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    /** Logger used by this class. Available to subclasses. */
    protected final Log logger = LogFactory.getLog(getClass());
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

   After inspecting the dependencies of our project with mvn dependency:dependency-list.

[INFO] \- org.springframework:spring-context:jar:3.1.1.RELEASE:compile
[INFO]    +- org.springframework:spring-aop:jar:3.1.1.RELEASE:compile
[INFO]    |  \- aopalliance:aopalliance:jar:1.0:compile
[INFO]    +- org.springframework:spring-beans:jar:3.1.1.RELEASE:compile
[INFO]    +- org.springframework:spring-core:jar:3.1.1.RELEASE:compile
[INFO]    +- org.springframework:spring-expression:jar:3.1.1.RELEASE:compile
[INFO]    \- org.springframework:spring-asm:jar:3.1.1.RELEASE:com

 Curiously, the class AbstractApplicationContext inside org.springframework:spring-context does not depend from commmons-logging of Apache.

The correction is rather simple : add the following lines to your pom.xml :

<dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <version>1.1</version>
</dependency>

A reader indicated me that :

Chin Huang   :

The Spring Reference Documentation explains why Spring does NOT depend on Apache commons-logging and recommends using instead SLF4J and its jcl-over-slf4j library which adapts the commons-logging API to the SLF4J API. 

 

Answer : The main problem is that nothing is indicated by maven that this choice exist and no suggestion is made by maven. That is a flaw would be interesting to fix in a new maven plugin. In Tocea, we are going to start a project to manage this kind of problem. Stay informed!

Published at DZone with permission of its author, Sylvain Leroy.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)