Lalit Mehra
Lalit Mehra

Reputation: 1273

Maven Dependency and Logging - Slf4j and Log4j

I am using Maven to manage project dependencies in a spring based project.

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.16</version>
    <!-- <scope>provided</scope> -->
    </dependency>

    <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.5</version>
    <!-- <scope>provided</scope> -->
</dependency>

However, some other projects deployed on the same server use slf4j and log4j libraries present in tomcat's lib directory and I cannot remove those.

Slf4J and Log4J version present in tomcat's lib directory are

slf4j-api-1.4.2

log4j-1.2.14

slf4j-log4j12-1.5.2

My project works fine when I remove these libraries from tomcat's lib directory and use the one mentioned in project's pom

When I comment the dependency in project's pom file and use the one's present in tomcat's lib below exception is thrown

> SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
java.lang.NoSuchMethodError: org.slf4j.impl.StaticLoggerBinder.getSingleton()Lorg/slf4j/impl/StaticLoggerBinder;
    at org.slf4j.LoggerFactory.bind(LoggerFactory.java:128)
    at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:107)
    at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:295)
    at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:269)
    at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:155)
    at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:131)
    at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:657)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:282)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4797)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5291)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
    at java.util.concurrent.FutureTask.run(FutureTask.java:166)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)

>May 21, 2014 11:57:27 AM org.apache.catalina.core.StandardContext startInternal
SEVERE: Error listenerStart
May 21, 2014 11:57:27 AM org.apache.catalina.core.StandardContext startInternal
SEVERE: Context [/onevalue] startup failed due to previous errors
May 21, 2014 11:57:27 AM org.apache.catalina.core.ApplicationContext log
INFO: Closing Spring root WebApplicationContext
May 21, 2014 11:57:27 AM org.apache.catalina.core.StandardContext listenerStop
SEVERE: Exception sending context destroyed event to listener instance of class org.springframework.web.context.ContextLoaderListener
java.lang.ExceptionInInitializerError
    at org.springframework.web.context.ContextLoaderListener.contextDestroyed(ContextLoaderListener.java:116)
    at org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4837)
    at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5484)
    at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:232)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:160)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
    at java.util.concurrent.FutureTask.run(FutureTask.java:166)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)
Caused by: java.lang.IllegalStateException: org.slf4j.LoggerFactory could not be successfully initialized. See also http://www.slf4j.org/codes.html#unsuccessfulInit
    at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:303)
    at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:269)
    at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:155)
    at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:131)
    at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:657)
    at org.springframework.web.context.ContextCleanupListener.<clinit>(ContextCleanupListener.java:43)
    ... 12 more

I also tried to use maven scope "provided" while keeping the libraries in tomcat's lib directory. Though the project runs, but now logging mechanism is not working, no logs are getting created, even the System.out.println() couldn't print anything on console window

Upvotes: 2

Views: 46070

Answers (2)

MrYo
MrYo

Reputation: 1817

<dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.5</version>
</dependency>

This is my configuration and it works fine for me.

Upvotes: 1

Niels Bech Nielsen
Niels Bech Nielsen

Reputation: 4859

It seems as if you need to downgrade your project to slf4j 1.4.2 to work with the log4j available in your tomcat. They are binary incompatible. You would also hang on to the <scope>provided</scope> afterwards, so you dont include them double.

The alternative is to get the other project to include the libraries themselves and remove from tomcat common. I know of no other exclusion mechanism on the tomcat.

For reference, and probably not helpful, I currently deploy on weblogic and it has a deployment specification that allows one to exclude server common classes and use bundled classes instead, such as the below snippet (with reference)

<wls:prefer-application-packages>
<!-- http://blog.terrencemiao.com/archives/annoying-slf4j-problem-in-weblogic-server-12c -->
  <wls:package-name>org.slf4j</wls:package-name>
    </wls:prefer-application-packages>

Upvotes: 2

Related Questions