Maven + SLF4J:使用需要两个不同 SLF4J 版本的两个不同依赖项时的版本冲突

Posted

技术标签:

【中文标题】Maven + SLF4J:使用需要两个不同 SLF4J 版本的两个不同依赖项时的版本冲突【英文标题】:Maven + SLF4J: Version conflict when using two different dependencies that require two different SLF4J versions 【发布时间】:2012-02-13 20:04:16 【问题描述】:

我有一个项目独立使用这两个依赖项:BoneCP 和 Hibernate。但是由于 SLF4J 及其版本冲突,它不起作用,因为 BoneCP 需要 SLF4J 1.5 而 Hibernate 需要 SLF4j 1.6。如您所知,不可能在 pom.xml 中对同一依赖项的两个不同版本进行重要处理。那么我能做些什么来解决这个惊人的 SLF4J 副作用???

我得到的错误是臭名昭著的:

SLF4J: The requested version 1.5.10 by your slf4j binding is not compatible with [1.6]
SLF4J: See http://www.slf4j.org/codes.html#version_mismatch for further details.

我需要添加这个,但不允许有两个不同版本的相同依赖:

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.5.10</version>
<scope>provided</scope>
</dependency>   

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.2</version>
<scope>provided</scope>
</dependency>   

Maven 依赖树:

[INFO] [dependency:tree execution: default-cli]
[INFO] org.mentawai:menta:war:1.0.5-SNAPSHOT
[INFO] +- javax.servlet.jsp:jsp-api:jar:2.0:provided
[INFO] +- javax.servlet:servlet-api:jar:2.5:provided
[INFO] +- javax.activation:activation:jar:1.1:compile
[INFO] +- javax.mail:mail:jar:1.4:compile
[INFO] +- javax.persistence:persistence-api:jar:1.0:compile
[INFO] +- org.slf4j:slf4j-log4j12:jar:1.5.10:compile
[INFO] |  +- org.slf4j:slf4j-api:jar:1.5.10:compile
[INFO] |  \- log4j:log4j:jar:1.2.14:compile
[INFO] +- org.hibernate:hibernate-core:jar:3.6.7.Final:compile
[INFO] |  +- antlr:antlr:jar:2.7.6:compile
[INFO] |  +- commons-collections:commons-collections:jar:3.1:compile
[INFO] |  +- dom4j:dom4j:jar:1.6.1:compile
[INFO] |  +- org.hibernate:hibernate-commons-annotations:jar:3.2.0.Final:compile
[INFO] |  +- org.hibernate.javax.persistence:hibernate-jpa-2.0-api:jar:1.0.1.Final:compile
[INFO] |  \- javax.transaction:jta:jar:1.1:compile
[INFO] +- javassist:javassist:jar:3.12.1.GA:compile
[INFO] +- junit:junit:jar:4.8.1:test
[INFO] +- c3p0:c3p0:jar:0.9.1.2:compile
[INFO] +- com.h2database:h2:jar:1.2.138:compile
[INFO] +- mysql:mysql-connector-java:jar:5.1.13:compile
[INFO] +- me.soliveirajr:mentawai:jar:2.3.3-SNAPSHOT:compile
[INFO] |  +- net.sf.json-lib:json-lib:jar:jdk15:2.3:compile
[INFO] |  |  +- commons-beanutils:commons-beanutils:jar:1.8.0:compile
[INFO] |  |  +- commons-logging:commons-logging:jar:1.1.1:compile
[INFO] |  |  \- net.sf.ezmorph:ezmorph:jar:1.0.6:compile
[INFO] |  +- org.jdom:jdom:jar:1.1:compile
[INFO] |  +- com.thoughtworks.xstream:xstream:jar:1.3.1:compile
[INFO] |  |  \- xpp3:xpp3_min:jar:1.1.4c:compile
[INFO] |  +- org.ajaxtags:ajaxtags:jar:1.2-beta3:compile
[INFO] |  |  +- javax.servlet:jstl:jar:1.0.6:compile
[INFO] |  |  +- taglibs:standard:jar:1.0.6:compile
[INFO] |  |  \- net.htmlparser:jericho-html:jar:2.1:compile
[INFO] |  +- jgroups:jgroups-all:jar:2.2.9.1:compile
[INFO] |  +- me.soliveirajr:menta-container:jar:0.9.8:compile
[INFO] |  +- me.soliveirajr:menta-bean:jar:1.1.1:compile
[INFO] |  +- me.soliveirajr:menta-regex:jar:0.9.5:compile
[INFO] |  +- org.beanshell:bsh:jar:2.0b4:compile
[INFO] |  +- com.jolbox:bonecp:jar:0.7.1.RELEASE:compile
[INFO] |  |  \- com.google.guava:guava:jar:r08:compile
[INFO] |  +- velocity:velocity-dep:jar:1.4:compile
[INFO] |  +- commons-fileupload:commons-fileupload:jar:1.2.2:compile
[INFO] |  +- commons-io:commons-io:jar:1.3.2:compile
[INFO] |  +- net.tanesha.recaptcha4j:recaptcha4j:jar:0.0.7:compile
[INFO] |  \- commons-dbcp:commons-dbcp:jar:1.4:compile
[INFO] |     \- commons-pool:commons-pool:jar:1.5.4:compile
[INFO] +- commons-lang:commons-lang:jar:2.5:compile
[INFO] \- asm:asm:jar:3.2:compile

【问题讨论】:

请添加您遇到的错误。此外,您不应该仅仅因为其他依赖项使用它而将 SLF4J 添加到您的 POM - 如果 直接使用它,您只需要添加它。 Maven 负责传递依赖,我怀疑它会引入 1.6,BoneCP 不会不高兴。 添加了错误。我相信我必须添加 SLF4J 的实现。所以问题是:Hibernate 需要 1.6 实现。 BoneCP 需要 1.5。这就是冲突! 【参考方案1】:

错误消息中提供的链接“http://www.slf4j.org/codes.html#version_mismatch”指出:

SLF4J 绑定指定一个工件,例如 slf4j-jdk14.jar 或 slf4j-log4j12.jar 用于将 slf4j 绑定到底层日志记录 框架,例如 java.util.logging 或 log4j。混合混合不同 slf4j-api.jar 版本和 SLF4J 绑定可能会导致问题。为了 例如,如果您使用的是 slf4j-api-1.6.6.jar,那么您还应该 使用 slf4j-simple-1.6.6.jar,使用 slf4j-simple-1.5.5.jar 不会 工作。

注意 从客户端的角度来看,所有版本的 slf4j-api 都是 兼容。使用 slf4j-api-N.jar 编译的客户端代码将运行 对于任何 N 和 M,slf4j-api-M.jar 都非常好。你只需要 确保您的绑定版本与 slf4j-api.jar。您不必担心版本 项目中给定依赖项使用的 slf4j-api.jar。你可以 始终使用任何版本的 slf4j-api.jar,只要 slf4j-api.jar 和它的绑定匹配,应该没问题。

鉴于所有版本的 slf4j-api 从客户端的角度来看都是可互换的,在不同版本的 slf4j-api 及其绑定的场景中,例如slf4j-log4j12 被拉入,在你的 POM 中显式声明它们为依赖项,如下所示:

<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-api</artifactId>
  <version>1.7.25</version>
</dependency>   

<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-log4j12</artifactId>
  <version>1.7.25</version>
</dependency>   

这里我假设您实际上不需要在提供的范围内声明 slf4j-api 和 slf4j-log4j12。

另见Introduction to the Dependency Mechanism,其中指出:

依赖中介 - 这决定了依赖的版本 当遇到工件的多个版本时将使用。 目前,Maven 2.0 仅支持使用“最近定义” 这意味着它将使用最接近的依赖版本 你的项目在依赖树中。 您始终可以保证 通过在项目的 POM 中明确声明版本。

【讨论】:

仅供参考,此回复来自 SLF4J 的作者。【参考方案2】:

我遇到了同样的错误。基本上,请注意类路径中有多个版本的 slf4j jar。

【讨论】:

【参考方案3】:

只排除1.5.10版本的SLF4J

 <dependency>
      <groupId>...</groupId>
      <artifactId>BoneCP</artifactId>
      <version>...</version>
      <exclusions>
        <exclusion>  <!-- declare the exclusion here -->
         <groupId>org.slf4j</groupId>
         <artifactId>slf4j-log4j12</artifactId>
         <version>1.5.10</version>
        </exclusion>
      </exclusions> 
    </dependency>

【讨论】:

+1 用于提及排除。 @chrisapotek - 您可能希望实际上从 BoneCP Hibernate 中排除 SLF4J,然后为 slf4j-api 和 slf4j-simple 手动将依赖项添加到您的 pom 中。那应该永远摆脱依赖冲突。 这里有一些误解:BoneCP 已绑定(需要)1.5。它与 API 绑定,而不是与您在上面尝试排除的实现绑定。我需要为 BoneCP 添加一个额外的实现。我无法切换 BoneCP 使用的 API 版本。检查问题中编辑的 mvn 依赖尝试。

以上是关于Maven + SLF4J:使用需要两个不同 SLF4J 版本的两个不同依赖项时的版本冲突的主要内容,如果未能解决你的问题,请参考以下文章

收到致命警报:protocol_version 构建失败 Gradle/Maven

如何配置SLF4J不同的日志实现

Java日志框架 -- SLF4J日志门面(入门案例SLF4J优点SLF4J日志绑定SL4J桥接旧的日志框架)

Java日志框架 -- SLF4J日志门面(入门案例SLF4J优点SLF4J日志绑定SL4J桥接旧的日志框架)

Java日志框架 -- SLF4J日志门面(入门案例SLF4J优点SLF4J日志绑定SL4J桥接旧的日志框架)

添加javax.servlet-api依赖项抛出org.slf4j.impl.StaticLoggerBinder无法加载但我不使用sl4j的异常,我使用百万美元