在类路径上找到多个绑定,并在类路径上检测到log4j-over-slf4j.jar和slf4j-log4j12.jar

时间:2018-12-17 06:57:45

标签: java gradle

我正在使用Gradle作为构建工具,在部署过程中,我遇到了以下我提到的一些问题。

Gradle构建任务没有问题,但是当我将其部署在tomcat8上时,它显示以下错误。

build.gradle依赖项文件如下:

dependencies {

    testCompile group: 'junit', name: 'junit', version: '4.12'

    compile group: 'javax.servlet', name: 'javax.servlet-api', version: '3.1.0'
    compile group: 'org.json', name: 'json', version: '20090211'

    // Apache Kafka Dependencies
    compile group: 'org.apache.kafka', name: 'kafka-clients', version: '2.0.0'
    compile group: 'org.apache.kafka', name: 'connect-json', version: '2.0.0'

    // Office365 authentication Dependencies
    compile group: 'com.microsoft.azure', name: 'adal4j', version: '1.6.0'
    runtime group: 'com.nimbusds', name: 'oauth2-oidc-sdk', version: '5.24.1'

    // Apache Hadoop HDFS Dependencies
    compile group: 'org.apache.hadoop', name: 'hadoop-hdfs', version: '2.9.1'
    compile group: 'org.apache.hadoop', name: 'hadoop-hdfs-client', version: '2.9.1'
    compile group: 'org.apache.hadoop', name: 'hadoop-common', version: '2.9.1'
    compile group: 'org.apache.hive', name: 'hive-jdbc', version: '2.3.3'

    // Spring Dependencies
    compile group: 'opensymphony', name: 'sitemesh', version: '2.4.2'
    compile group: 'org.springframework', name: 'spring-webmvc', version: '4.3.14.RELEASE'
    compile group: 'org.springframework', name: 'spring-tx', version: '4.3.14.RELEASE'

    // Mysql Connector Dependency
    compile group: 'mysql', name: 'mysql-connector-java', version: '6.0.6'

    // Apache Spark Dependencies
    compile group: 'com.databricks', name: 'spark-csv_2.11', version: '1.5.0'
    compile group: 'org.apache.spark', name: 'spark-sql_2.11', version: '2.3.0'
    compile group: 'org.apache.spark', name: 'spark-core_2.11', version: '2.3.0'
    compile group: 'com.fasterxml.jackson.module', name: 'jackson-module-scala_2.11', version: '2.8.8'

    // Apache Storm & Apache Kafka Consumer Dependencies
    compile group: 'org.apache.storm', name: 'storm-core', version: '1.2.0'
    compile group: 'org.apache.storm', name: 'storm-kafka', version: '1.2.0'
    compile group: 'org.apache.kafka', name: 'kafka_2.10', version: '0.9.0.1'

    // Elasticsearch Dependencies
    compile group: 'org.elasticsearch.client', name: 'elasticsearch-rest-high-level-client', version: '6.5.2'
    compile group: 'org.elasticsearch', name: 'elasticsearch', version: '6.5.2'
    //compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.11.1'
    //compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.11.1'
    //compile group: 'org.slf4j', name: 'slf4j-log4j12'
}   

错误消息:

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/home/sagarjoshi/opt/tomcat-analytics/apache-tomcat-8.0.53/webapps/analytics/WEB-INF/lib/slf4j-log4j12-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/sagarjoshi/opt/tomcat-analytics/apache-tomcat-8.0.53/webapps/analytics/WEB-INF/lib/log4j-slf4j-impl-2.8.2.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/sagarjoshi/opt/tomcat-analytics/apache-tomcat-8.0.53/webapps/analytics/WEB-INF/lib/logback-classic-1.0.9.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Detected both log4j-over-slf4j.jar AND slf4j-log4j12.jar on the class path, preempting StackOverflowError. 
SLF4J: See also http://www.slf4j.org/codes.html#log4jDelegationLoop for more details.
17-Dec-2018 11:32:29.244 SEVERE [RMI TCP Connection(2)-127.0.0.1] org.apache.catalina.core.StandardContext.startInternal Error during ServletContainerInitializer processing
 javax.servlet.ServletException: Failed to instantiate WebApplicationInitializer class
    at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:155)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5352)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:755)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:731)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717)
    at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1730)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
    at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:485)
    at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:434)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
    at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1468)
    at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:76)
    at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1309)
    at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1401)
    at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:829)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:357)
    at sun.rmi.transport.Transport$1.run(Transport.java:200)
    at sun.rmi.transport.Transport$1.run(Transport.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:573)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:834)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

2 个答案:

答案 0 :(得分:0)

检查项目依赖性。真的需要这么多编译依赖项吗?检查所有API并使用匹配范围。可能runtime通常就足够了。

您的程序对日志记录API和桥接(log4和slf4j的日志记录)有多个定义。确定要使用哪一个,并相应地声明依赖项。提供使用的日志记录API的配置。

请参见slf4j - bridges,桥接如何工作。

如果您要标识具有不良瞬时依赖关系的项目,请使用gradle依赖关系树(请参见gradle - inspecting dependencies

gradlew dependencies

可能在分析了依赖关系之后,您可能需要根据运行时环境排除一些依赖关系。请参阅gradle - managing transient dependencies的操作方法。

答案 1 :(得分:0)

SLF4J API 旨在一次绑定一个且仅一个底层日志框架。如果类路径上存在多个绑定,SLF4J 将发出警告,列出这些绑定的位置。

当类路径上有多个绑定可用时,选择一个且仅一个您希望使用的绑定,然后删除其他绑定。例如,如果您在类路径上同时具有 slf4j-simple-2.0.0-alpha2.jar 和 slf4j-nop-2.0.0-alpha2.jar 并且您希望使用 nop(无操作)绑定,则删除slf4j-simple-2.0.0-alpha2.jar 来自类路径。

SLF4J 在此警告中提供的位置列表通常提供足够的信息来识别依赖项,将不需要的 SLF4J 绑定传递到您的项目中。在您项目的 pom.xml 文件中,在声明不道德的依赖项时排除此 SLF4J 绑定。例如,cassandra-all 版本 0.8.1 将 log4j 和 slf4j-log4j12 声明为编译时依赖项。因此,当您在项目中包含 cassandra-all 作为依赖项时,cassandra-all 声明将导致 slf4j-log4j12.jar 和 log4j.jar 作为依赖项被拉入。如果您不想使用 log4j 作为 SLF4J 后端,您可以指示 Maven 排除这两个工件,如下所示:

<dependencies>
  <dependency>
    <groupId> org.apache.cassandra</groupId>
    <artifactId>cassandra-all</artifactId>
    <version>0.8.1</version>

    <exclusions>
      <exclusion> 
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
      </exclusion>
      <exclusion> 
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
      </exclusion>
    </exclusions> 

  </dependency>
</dependencies>