5

I have really struggled with the loading of logback-classic as a transitive dependency problem. I follow the advice found here on stackoverflow, but, it keeps re-occurring.

I use maven exclusions to try to try to control it, it does not appear at all in my pom dependencies hierarchy. And yet it still gets loaded!

Here is my runtime trace

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/home/david/.m2/repository/de/ruedigermoeller/kontraktor-http/3.33/kontraktor-http-3.33.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/david/.m2/repository/ch/qos/logback/logback-classic/1.2.1/logback-classic-1.2.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
W 13:22:24:837 : DispatcherThread 1 : DispatcherThread : 
java.lang.NoSuchMethodError: org.slf4j.impl.StaticLoggerBinder.getLoggerFactoryClassStr()Ljava/lang/String;
at org.slf4j.LoggerFactory.reportActualBinding(LoggerFactory.java:271)
at org.slf4j.LoggerFactory.bind(LoggerFactory.java:143)
at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:120)
at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:331)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:283)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:304)
at org.quartz.impl.StdSchedulerFactory.<init>(StdSchedulerFactory.java:284)
at org.quartz.impl.StdSchedulerFactory.getDefaultScheduler(StdSchedulerFactory.java:1539)
at uk.co.example.ExampleEwsService.init(ExampleEwsService.java:296)

Part of the problem is that the Kontraktor framework overrides the StaticLoggerBinder.getLoggerFactoryClassStr method. But it is easy to make sure it gets loaded first and then to exclude the logback-classic from quartz, which is loading it, as follows:

    <dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz</artifactId>
        <version>2.2.3</version>
        <exclusions>
            <exclusion>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz-jobs</artifactId>
        <version>2.2.3</version>
    </dependency>

At this point slf4j is only loaded by kontraktor. logback-classic appears nowhere in the dependency:tree

[INFO] +- de.ruedigermoeller:kontraktor:jar:3.33:compile
[INFO] |  +- org.jctools:jctools-core:jar:1.0:compile
[INFO] |  \- de.ruedigermoeller:fst:jar:2.44.5:compile
[INFO] |     +- com.fasterxml.jackson.core:jackson-core:jar:2.5.3:compile
[INFO] |     +- org.javassist:javassist:jar:3.19.0-GA:compile
[INFO] |     +- org.objenesis:objenesis:jar:2.1:compile
[INFO] |     \- com.cedarsoftware:java-util:jar:1.9.0:compile
[INFO] |        \- com.cedarsoftware:json-io:jar:2.5.1:compile
[INFO] +- de.ruedigermoeller:kontraktor-http:jar:3.33:compile
[INFO] |  +- io.github.lukehutch:fast-classpath-scanner:jar:1.2.3:compile
[INFO] |  +- org.apache.httpcomponents:httpasyncclient:jar:4.1:compile
[INFO] |  |  +- org.apache.httpcomponents:httpcore:jar:4.4.1:compile
[INFO] |  |  +- org.apache.httpcomponents:httpcore-nio:jar:4.4.1:compile
[INFO] |  |  +- org.apache.httpcomponents:httpclient:jar:4.4.1:compile
[INFO] |  |  |  \- commons-codec:commons-codec:jar:1.9:compile
[INFO] |  |  \- commons-logging:commons-logging:jar:1.2:compile
[INFO] |  +- javax.websocket:javax.websocket-api:jar:1.1:compile
[INFO] |  +- io.undertow:undertow-core:jar:1.2.8.Final:compile
[INFO] |  |  +- org.jboss.logging:jboss-logging:jar:3.1.4.GA:compile
[INFO] |  |  +- org.jboss.xnio:xnio-api:jar:3.3.1.Final:compile
[INFO] |  |  \- org.jboss.xnio:xnio-nio:jar:3.3.1.Final:runtime
[INFO] |  +- io.undertow:undertow-websockets-jsr:jar:1.2.8.Final:compile
[INFO] |  |  +- io.undertow:undertow-servlet:jar:1.2.8.Final:compile
[INFO] |  |  |  +- org.jboss.spec.javax.servlet:jboss-servlet-api_3.1_spec:jar:1.0.0.Final:compile
[INFO] |  |  |  \- org.jboss.spec.javax.annotation:jboss-annotations-api_1.2_spec:jar:1.0.0.Final:compile
[INFO] |  |  \- org.jboss.spec.javax.websocket:jboss-websocket-api_1.1_spec:jar:1.1.0.Final:compile
[INFO] |  +- org.slf4j:slf4j-api:jar:1.7.12:compile
[INFO] |  \- org.jsoup:jsoup:jar:1.8.2:compile
[INFO] +- org.apache.logging.log4j:log4j-api:jar:2.5:compile
[INFO] +- org.apache.logging.log4j:log4j-core:jar:2.5:compile
[INFO] +- org.quartz-scheduler:quartz:jar:2.2.3:compile
[INFO] |  \- c3p0:c3p0:jar:0.9.1.1:compile
[INFO] +- org.quartz-scheduler:quartz-jobs:jar:2.2.3:compile

So simple question, how does logback-classic get loaded, and who is loading it?

oldDave
  • 395
  • 6
  • 25
  • the log shows that you still have logback-classic-1.2.1.jar in your classpath. Maybe try mvn clean ,or what ever clean command in your ide can solve this problem. – Mobility Apr 10 '17 at 13:02
  • Tried both mvn clean install and maven clean package, no change to the outcome. I know it is in my classpath, what I need to find out is who is including it there. – oldDave Apr 10 '17 at 14:03
  • 2
    Tried other options with the dependency goal and looking specifically for the dependency? e.g. `mvn dependency:tree -Dincludes=org.slf4j:slf4j-api` – Darren Forsythe Apr 10 '17 at 19:01
  • This method allowed me to find the dependency. It seems that dependency:tree is only so deep. The -Dincludes searches the full hierarchy for the specified dependency. – oldDave Apr 11 '17 at 09:20

1 Answers1

3

The comment by Darren Forsythe is the answer. This -Dincludes=ch.qos.logback:logback-classic allowed me to find the dependency. It seems that dependency:tree search is only so deep. The -Dincludes searches the full hierarchy for the specified dependency.

oldDave
  • 395
  • 6
  • 25