RuedigerMoeller / kontraktor

distributed Actors for Java 8 / JavaScript
GNU Lesser General Public License v3.0
343 stars 48 forks source link

slf4j version clash #32

Open davidwynter opened 8 years ago

davidwynter commented 8 years ago

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:

`

de.ruedigermoeller
           <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.

RuedigerMoeller commented 8 years ago

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 ...

davidwynter commented 8 years ago

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....

davidwynter commented 7 years ago

This has come back to cause a problem, see here - http://stackoverflow.com/questions/40310657/multiple-slf4j-bindings-even-after-pom-exclusion

RuedigerMoeller commented 7 years ago

i'll exlcude slf4j in one of the next versions, problem is i need to redirect undertow logging somehow ..

davidwynter commented 7 years ago

How about AspectJ - http://www.yegor256.com/2014/06/01/aop-aspectj-java-method-logging.html

davidwynter commented 7 years ago

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.

davidwynter commented 7 years ago

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 "";
}
RuedigerMoeller commented 7 years ago

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.

RuedigerMoeller commented 7 years ago

this also means you should verify things work if you pull and use the current "trunk" branch

davidwynter commented 7 years ago

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.

RuedigerMoeller commented 7 years ago

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.