0

We are facing sl4j version conflicts in gradle with Storm 1.0.1 and elasticsearch 5.2.

We found that the ElasticSearch needs bridge log4j-to-slf4j so that we can use desired loggers. Here we are trying to use logback-classic with slf4j.

The dependencies are defined as below:

dependencies {
    compile 'org.slf4j:slf4j-api:1.7.21'
    compile 'org.apache.logging.log4j:log4j-to-slf4j:2.6.2'
    compile 'ch.qos.logback:logback-classic:1.1.10'
    provided ('org.apache.storm:storm-core:1.0.1') {
        exclude(group: 'org.slf4j', module: 'slf4j-api')
    }
    compile 'org.elasticsearch:elasticsearch:5.2.0'
    compile 'org.elasticsearch.client:x-pack-transport:5.2.0'
}

To resolve this I tried to exclude the slf4j from storm-core and add the same later as below:

configurations.all {
    resolutionStrategy {
        eachDependency { DependencyResolveDetails dependencyResolveDetails ->
            final requestedDependency = dependencyResolveDetails.requested
            if (requestedDependency.group == 'org.slf4j' && requestedDependency.name == 'slf4j-api') {
                requestedDependency.setVersion "1.7.7"
            }
         }
    }
}

But when topology is submitted we get error : SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [jar:file:/Users/gauthamr05/Documents/Apps/Storm/apache-storm-1.0.1/lib/log4j-slf4j-impl-2.1.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [jar:file:/Users/gauthamr05/Documents/workspace/xyz_app/build/libs/FullIndexing.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation. SLF4J: Actual binding is of type [org.apache.logging.slf4j.Log4jLoggerFactory] Exception in thread "main" java.lang.StackOverflowError at org.apache.logging.log4j.spi.LoggerRegistry.getOrCreateInnerMap(LoggerRegistry.java:140) at org.apache.logging.log4j.spi.LoggerRegistry.hasLogger(LoggerRegistry.java:154) at org.apache.logging.slf4j.SLF4JLoggerContext.getLogger(SLF4JLoggerContext.java:38) at org.apache.logging.slf4j.Log4jLoggerFactory.newLogger(Log4jLoggerFactory.java:37) at org.apache.logging.slf4j.Log4jLoggerFactory.newLogger(Log4jLoggerFactory.java:29) at org.apache.logging.log4j.spi.AbstractLoggerAdapter.getLogger(AbstractLoggerAdapter.java:47) at org.apache.logging.slf4j.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:29) at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:277)

2 Answers2

0

As the exception states, there's two jars containing StaticLoggerBinder.class.

  • /Users/gauthamr05/Documents/Apps/Storm/apache-storm-1.0.1/lib/log4j-slf4j-impl-2.1.jar
  • /Users/gauthamr05/Documents/workspace/xyz_app/build/libs/FullIndexing.jar

Question: Is xyz_app/build/libs/FullIndexing.jar one of your own projects?

If it is your own jar, I'm taking a bit of a guess here, but I'm guessing that org/slf4j/impl/StaticLoggerBinder.java is packed inside one of the jars on your classpath. There's a wierd default of javac where it will compile any .java files found in jars on your classpath. This can be switched off by

compileJava.options.compilerArgs << '-implicit:none'

See here and here

lance-java
  • 25,497
  • 4
  • 59
  • 101
0

Found a way to shadow the log4j classes in the final jar.

Following are the configurations:

apply plugin: 'com.github.johnrengelman.shadow'

subprojects {
    shadowJar
}

dependencies {
    compile 'org.slf4j:slf4j-api:1.7.22'
    compile 'ch.qos.logback:logback-classic:1.1.10'

    compileOnly("org.apache.storm:storm-core:1.0.1") {
        exclude module: "log4j-slf4j-impl"
        exclude module: "slf4j-api"
        exclude module: "log4j-to-slf4j"
    }

    // ElasticSearch and X-Pack
    compile 'org.elasticsearch:elasticsearch:5.2.0'
    compile 'org.elasticsearch.client:x-pack-transport:5.2.0'

    compile 'org.apache.logging.log4j:log4j-api:2.7'
    compile 'org.apache.logging.log4j:log4j-core:2.7'
}

shadowJar {
    relocate 'org.apache.logging.log4j', 'gautham.elasticsearch.org.apache.logging.log4j'

    zip64 true
    transform(ServiceFileTransformer) {
        path = 'META-INF/vesta*'
    }

    manifest {
        attributes 'Implementation-Title': 'Storm Topology',
            'Implementation-Version': 1.0,
            'Main-Class': 'com.gautham.topology.StormTopology'
    }

    baseName = 'StormTopology'

    mergeServiceFiles()

    exclude "META-INF/*.SF"
    exclude 'META-INF/*.DSA'
    exclude 'META-INF/*.RSA'
    exclude "LICENSE*"
}