Tomcat: java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory

Imagine this: you have laid down the foundation of your brand new Spring-based web application. You have just downloaded and installed a mint Tomcat server to deploy you app on it and…

The web application just won’t start. Tomcat’s logs display an “Encountered exception org.apache.catalina.LifecycleException” and the logs point to a ” java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory” exception. Bummer!

It’s probably…

At this point most of us will look into their web application and make sure their logger has been set up correctly to use Logback or Log4j.

Maybe we have forgotten our slf4j bridging module?

Then you notice that by adding Commons Logging to Tomcat’s libs/ folder it just seems to get rid of the problem. That’s it: Tomcat forgot to pack a library. Problem solved!

Gotcha!

Well it’s a bit more complicated than that… And it’s not Tomcat’s fault either!

Looking closely at the logs indicates that it is Spring who is requesting the dependency:

Yep, Spring has one mandatory external dependency, and it’s related to logging. Their choice was to rely on Jakarta Commons Logging (JCL) by default. This is very convenient in itself, but makes switching to a different logger a bit trickier than the developers of Spring had wished (though I think they’re being hard on themselves. Come on, give them some credit for their work!).

It amounts to this. First we make sure that we exclude commons-logging from the Spring core:

Then we bring in our own logger, for example Logback on SLF4J. We make sure we bridge JCL over to SLF4J, like this:

(note that I have omitted the <version> tags: in my case they are handled by Spring IO Platform)

With this, Spring’s logging requests will be redirected on SLF4J, which we asked to rely upon Logback.

Just add a logback.xml configuration, and Bob’s your uncle:

Now you should be able to re-deploy your Spring web application on your Tomcat server without any problems.

Cheers!