25

I have a project that use both dependencies independently: BoneCP and Hibernate. But thanks to SLF4J and its version conflicts it does not work because BoneCP requires SLF4J 1.5 and Hibernate requires SLF4j 1.6. As you know it is not possible to important two different versions of the same dependency in your pom.xml. So what can I do to workaround this amazing SLF4J side-effect???

The error I get is the infamous:

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.

I would need to add this, but same dependency with two different versions is not allowed:

<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 dependency tree:

[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
chrisapotek
  • 6,007
  • 14
  • 51
  • 85
  • 1
    Please add the error you are getting. Also, you should not be adding SLF4J to your POM just because other dependencies use it - you only need to add it if _you_ use it directly. Maven takes care of the transitive dependencies and I suspect it will pull in 1.6 and BoneCP will not be unhappy. – SingleShot Jan 19 '12 at 05:23
  • Error added. I believe I DO have to add an implementation of SLF4J. So the problem is: Hibernate requires 1.6 implementation. BoneCP requires 1.5. That's the clash! – chrisapotek Jan 19 '12 at 05:28

2 Answers2

37

The link provided in the error message, "http://www.slf4j.org/codes.html#version_mismatch", states:

An SLF4J binding designates an artifact such as slf4j-jdk14.jar or slf4j-log4j12.jar used to bind slf4j to an underlying logging framework, say, java.util.logging or log4j. Mixing mixing different versions of slf4j-api.jar and SLF4J binding can cause problems. For example, if you are using slf4j-api-1.6.6.jar, then you should also use slf4j-simple-1.6.6.jar, using slf4j-simple-1.5.5.jar will not work.

NOTE From the client's perspective all versions of slf4j-api are compatible. Client code compiled with slf4j-api-N.jar will run perfectly fine with slf4j-api-M.jar for any N and M. You only need to ensure that the version of your binding matches that of the slf4j-api.jar. You do not have to worry about the version of slf4j-api.jar used by a given dependendency in your project. You can always use ANY version of slf4j-api.jar, and as long as the version of slf4j-api.jar and its binding match, you should be fine.

Given that all versions of slf4j-api are interchangeable from the clients perspective, in the scenario where different versions of slf4j-api and its binding e.g. slf4j-log4j12 are pulled in, explicitly declare them as dependencies in your POM as follows:

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

Here I am assuming that you do not actually need to declare slf4j-api and slf4j-log4j12 in the provided scope.

See also Introduction to the Dependency Mechanism which states:

Dependency mediation - this determines what version of a dependency will be used when multiple versions of an artifact are encountered. Currently, Maven 2.0 only supports using the "nearest definition" which means that it will use the version of the closest dependency to your project in the tree of dependencies. You can always guarantee a version by declaring it explicitly in your project's POM.

Ceki
  • 26,753
  • 7
  • 62
  • 71
5

Just exclude 1.5.10 version of 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>
e-zinc
  • 4,491
  • 2
  • 20
  • 17
  • 1
    +1 for mentioning exclusion. @chrisapotek - you might want to actually excluse SLF4J from both BoneCP **and** Hibernate, then manually add dependencies to your pom for both slf4j-api and slf4j-simple. That should get rid of the dependency clash for good. – Perception Jan 19 '12 at 06:43
  • 1
    Something is misunderstood here: BoneCP is bound (needs) 1.5. It is bound to the API and NOT to the implementation which you are trying to exclude above. I need to INCLUDE an extra implementation for BoneCP. I cannot SWITCH the API version used by BoneCP. Check the mvn dependency try edited in the question. – chrisapotek Jan 19 '12 at 14:39