slf4j version clash
davidwynter opened this issue · 11 comments
I solved this by deleting the /home/david/.m2/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.0 directory. Why it was using this I do not understand.
I have this exception
SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [jar:file:/home/david/.m2/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.0/log4j-slf4j-impl-2.0.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [jar:file:/home/david/.m2/repository/de/ruedigermoeller/kontraktor-http/3.26/kontraktor-http-3.26.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation. Exception in thread "main" 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.jboss.logging.Slf4jLoggerProvider.getLogger(Slf4jLoggerProvider.java:29) at org.jboss.logging.LoggerProviders.find(LoggerProviders.java:33) at org.jboss.logging.LoggerProviders.<clinit>(LoggerProviders.java:28) at org.jboss.logging.Logger.getLogger(Logger.java:2163) at org.jboss.logging.Logger$1.run(Logger.java:2263) at java.security.AccessController.doPrivileged(Native Method) at org.jboss.logging.Logger.getMessageLogger(Logger.java:2227) at org.jboss.logging.Logger.getMessageLogger(Logger.java:2214) at org.xnio._private.Messages.<clinit>(Messages.java:56) at org.xnio.Xnio.<clinit>(Xnio.java:93) at io.undertow.Undertow.start(Undertow.java:97) at org.nustaq.kontraktor.remoting.http.Http4K.getServer(Http4K.java:94) at org.nustaq.kontraktor.remoting.http.builder.BldFourK.build(BldFourK.java:106) at uk.co.mycompany.quokka.MyMain.main(MyMain.java:64)
So I thought that kontraktor-http was using an earlier version of slf4j so excluded the alternate version in the pom.xml like so:
<dependency> <groupId>de.ruedigermoeller</groupId> <artifactId>kontraktor-http</artifactId> <version>${kontraktor.version}</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> <exclusion> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> </exclusion> </exclusions> </dependency>
But that makes no difference. I am using V2.6.2 of log4j2 and 3.26 of Kontraktor.
Weirdly mvn dependency:tree only shows one version of slf4j used by kontraktor-http, but the stack trace shows 2 in use.
I had similar problems in the past
<dependency>
<groupId>org.deeplearning4j</groupId>
<artifactId>deeplearning4j-ui</artifactId>
<version>0.4-rc3.8</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.deeplearning4j</groupId>
<artifactId>deeplearning4j-nlp</artifactId>
<version>0.4-rc3.8</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.nd4j</groupId>
<artifactId>nd4j-jblas</artifactId>
<version>0.4-rc3.6</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
</exclusions>
</dependency>
I don't remember the details however the mvn excerpt above was the solution ...
Yes, I have the exclusions already there. But they are not excluding the slf4j? According to the maven documentation the exclusion works down the entire hierarchy. So not sure what is happening. The fact the slf4j only shows up once in the mvn dependency:tree is also confusing.
I downgraded the version of log4j to V2.5 where it used slf4j V1.7.12. So now kontraktor-http and log4j are using the same version of slf4j. But am still getting the same error....
This has come back to cause a problem, see here - http://stackoverflow.com/questions/40310657/multiple-slf4j-bindings-even-after-pom-exclusion
i'll exlcude slf4j in one of the next versions, problem is i need to redirect undertow logging somehow ..
How about AspectJ - http://www.yegor256.com/2014/06/01/aop-aspectj-java-method-logging.html
I sorted out my problem, I just added the missing method to the implementation of StaticLoggerBinder you did and it all seems to work. Interestingly most implementation of getLoggerFactoryClassStr throw UnsupportedOperationException("This code should never make it into the jar"). what a mess.
Could you include this method in your implementation of StaticLoggerBinder? It will save me tracking your new version and modifying them locally each time you do a release. It will save incompatibility with a few of the libs that use it. pom.xml dependency exclusions don't work.
public String getLoggerFactoryClassStr() {
return "";
}
I can do that. Btw do you use json encoding for your service architecture ?
I doing some heavy changes currently on kontraktor remoting, so there might be side effects. Probably will have to branch.
this also means you should verify things work if you pull and use the current "trunk" branch
OK, noted. I tend to use JSON encoding. But of course only "need" it for the js4k support. I can use FSTSer if need be for communicating with my 6 different service components.
well stick with 3.32 until further notice, i'll test the update with our system which should give good test coverage. change is, that it will be possible to forward remote messages without actually unpacking serialized classes of remote calls. This is required to build gateways/load balancers whithout requiring application level classes for (de)serialization.