Maven Class path error multiple SLF4J bindings - maven

I have been getting this error while trying to do a MAVEN INSTALL. I tried exclusions, but not sure the where to include in pom file. Let me how and what exclusion tags should i include in my pom file. I am also attaching my pom file snippet where to include the exclusions`SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in
[jar:file:/C:/Users/147188/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in
[jar:file:/C:/Users/147188/.m2/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.10.0/log4j-slf4j-impl-2.10.0.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
[ch.qos.logback.classic.util.ContextSelectorStaticBinder]
POM file:
<!-- Start of required part to make log4j work -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- End of required part to make log4j work -->

1 Run
mvn dependency:tree
to see which package import org.slf4j
2 keep one, and exclude other
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>

Correct way to exclude default logging, and configure log4j for logging.
Add this dependency in Spring Boot project, if it is not already there
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
Refer Spring Logging - How To.

That message indicates that you are bringing in both logback-classic and log4j-slf4j-impl, which both want to be the logging framework for SLF4J to bind to. If you're not sure which dependency is bringing in which other dependencies, I find it very useful to run "mvn dependency:tree" to see the tree of dependencies being used. That should give you enough information to figure out which logging framework binding you need to exclude.
As the documentation that the warning points to you says,
Embedded components such as libraries or frameworks should not declare a dependency on any SLF4J binding but only depend on slf4j-api. When a library declares a compile-time dependency on a SLF4J binding, it imposes that binding on the end-user, thus negating SLF4J's purpose. When you come across an embedded component declaring a compile-time dependency on any SLF4J binding, please take the time to contact the authors of said component/library and kindly ask them to mend their ways.
You pretty much want to exclude all actual logging frameworks from all dependencies, so that the only logging framework being used is the one you've explicitly added. I even often find it useful to set up some maven-enforcer-plugin bannedDependencies rules to ensure that I don't accidentally bring in another logging framework when updating my dependencies. It can also be helpful to use dependencyManagement sections in your POM to ensure that all your dependencies use the same version of slf4j-api.

I ran into same log4j-slf4j multiple binding issue. There are multiple reasons which caused this issue (Struggled a lot for this issue :) ). Please find below comments.
I was using Spring-Boot version 1.4.7, which internally configured with slf4j-1.7.25 version. Below is the url link, where you can find Spring-Boot version and respective module versions.
https://repo1.maven.org/maven2/org/springframework/boot/spring-boot-dependencies/
It seems when you use "spring-boot-starter" dependency, SB(Spring-Boot) will automatically download all these dependent modules. In my project, i was using slf4j-1.7.21, which created multiple slf4j version issue. In short, SB was not able to identify which slf4j version to use at runtime. So, first I changed my slf4j version to 1.7.25(which is compatible with Spring-Boot version 1.4.7).
Next you need to exclude right module (in my case exclusion of log4j-over-slf4j, logback-classic worked). You need to add below exclusions in all of spring-boot-starter-** module. For Eg : Here I am adding exclusion for spring-boot-starter-data-redis.
Hope this will resolve issue.

Related

Find all dependencies that include a given package

I excluded an artifact because it causes conflicts, namely the jsr311-api given below. Yet when I run the generated jar I'm still getting the java.lang.NoSuchMethodError error. I suspect that another dependency is also including this artifact. How can I find out which one? My dependency list is quite large. Which dependencies include the package javax.ws.rs.core?
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-kernel</artifactId>
<version>1.7.3</version>
<exclusions>
<!-- Causes java.lang.NoSuchMethodError: javax.ws.rs.core.Response$Status$Family.familyOf(I)Ljavax/ws/rs/core/Response$Status$Family; -->
<exclusion>
<artifactId>jsr311-api</artifactId>
<groupId>javax.ws.rs</groupId>
</exclusion>
</exclusions>
</dependency>
Go to
http://search.maven.org/#advancedsearch%7Cgav
and use classname search to find
javax.ws.rs.core.Response
If you use a Nexus 2.x in your company, you can use classname search there as well.
If you want to find out where a given artifact (that you e.g. found by classnmae search) comes from, use dependency:tree in Maven.
In my case the mistake was that I had to manually add the javaee api and I set <scope>provided</scope> which was a mistake, fixing this solved the problem.
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope><!-- remove this -->
</dependency>

Exclude package from being pulled in from an external jar in maven assembly

We had a bug whereby our logger stopped doing anything. In the end, we tracked it down to an external dependency, say:
<dependency>
<groupId>com.bob</groupId>
<artifactId>alice</artifactId>
<version>1.2.3</version>
</dependency>
which has it's own slf4j implementation. I had changed our pom so this dependency was listed first, which is what triggered the bug. Moving the dependency back to being listed last fixed the issue (so that the usual log4j implementation was used).
This seems like a very fragile fix. The "correct" fix would seem to be to get the maven assembly plugin to exclude importing, from the alice.jar file, any file in the org.slf4j package. We tried adding something to our custom assembly xml file, like:
<dependencySets>
<dependencySet>
<unpack>true</unpack>
<unpackOptions>
<excludes>
<exclude>com.bob:alice:org/slf4j/*</exclude>
However, this didn't work. The best I could do was:
<exclude>org/slf4j/*</exclude>
But this excludes all copies of that package, which obviously breaks everything.
What is the correct way to do this exclusion?
try this :
<dependency>
<groupId>com.bob</groupId>
<artifactId>alice</artifactId>
<version>1.2.3</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
And then add the dependency slf4j like this : (You can modify the version of the slf4j)
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.5.6</version>
</dependency>

activemq-all forces me to use log4j slf4j implementation

I would like to use the logback slf4j implementation in my application, but activemq-all is spoiling the classpath by including the log4j implementation classes. I'm not the only one facing that problem, as witnessed by for instance multiple SLF4J bindings Error with activemq-all-5.6.0.jar. According to that post I have to replace activemq-all by
org.apache.activemq:activemq-camel
org.apache.activemq:activemq-core
org.apache.activemq:activemq-console
org.apache.activemq:activemq-jaas
org.apache.activemq:activemq-optional
org.apache.activemq:kahadb
org.apache.geronimo.specs:geronimo-jms_1.1_spec
org.apache.geronimo.specs:geronimo-jta_1.0.1B_spec
org.apache.geronimo.specs:geronimo-j2ee-management_1.1_spec
org.apache.geronimo.specs:geronimo-annotation_1.0_spec.
The problem is that I don't have the complete maven dependencies (group id, artifact id, version) for these artifacts. Can someone provide me with a ready-to-use replacement for
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.9.0</version>
</dependency>
You can use active mq core library. Please note that active mq is backward compatible for client.
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-core</artifactId>
<version>5.4.3</version>
<exclusions>
<exclusion>
<artifactId>org.slf4j</artifactId>
<groupId>slf4j-log4j12</groupId>
</exclusion>
<exclusion>
<artifactId>log4j</artifactId>
<groupId>log4j</groupId>
</exclusion>
</exclusions>
</dependency>
In a nutshell, you have already listed group id/artifact id separated by a colon for the artifact you found. Please note that these satisfy some usecase with ActiveMQ 5.6. For instance activemq-core is not really valid any more - use activemq-client and activemq-broker instead.
Currently, these artifact are bundled in activemq-all. But you may want to check out the pom.xml for your version of choice (this list might change over time). You probably won't need all of them unless you are about to embedd a broker with all transports, plugins and configurations within your applications.
<artifactSet>
<includes>
<include>${project.groupId}:activemq-client</include>
<include>${project.groupId}:activemq-openwire-legacy</include>
<include>${project.groupId}:activemq-camel</include>
<include>${project.groupId}:activemq-jaas</include>
<include>${project.groupId}:activemq-broker</include>
<include>${project.groupId}:activemq-console</include>
<include>${project.groupId}:activemq-shiro</include>
<include>${project.groupId}:activemq-spring</include>
<include>${project.groupId}:activemq-pool</include>
<include>${project.groupId}:activemq-jms-pool</include>
<include>${project.groupId}:activemq-amqp</include>
<include>${project.groupId}:activemq-http</include>
<include>${project.groupId}:activemq-mqtt</include>
<include>${project.groupId}:activemq-stomp</include>
<include>${project.groupId}:activemq-kahadb-store</include>
<include>${project.groupId}:activemq-leveldb-store</include>
<include>${project.groupId}:activemq-jdbc-store</include>
<include>org.apache.activemq.protobuf:activemq-protobuf</include>
<include>org.fusesource.hawtbuf:hawtbuf</include>
<include>org.jasypt:jasypt</include>
<include>org.apache.geronimo.specs:geronimo-jms_1.1_spec</include>
<include>org.apache.geronimo.specs:geronimo-jta_1.0.1B_spec</include>
<include>org.apache.geronimo.specs:geronimo-j2ee-management_1.1_spec</include>
<include>org.apache.geronimo.specs:geronimo-annotation_1.0_spec</include>
<include>org.slf4j:slf4j-api</include>
<include>org.slf4j:slf4j-log4j12</include>
<include>log4j:log4j</include>
</includes>
</artifactSet>
Ok, the version number for org.apache.activemq should simply be the release you want to use. For the geronimo specs, this is not so obvious.
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jms_1.1_spec</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-j2ee-management_1.1_spec</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-annotation_1.0_spec</artifactId>
<version>1.1.1</version>
</dependency>
I was also facing this same issue with activemq-all API and I replaced this dependency with this below dependency and it worked for me.
<!-- https://mvnrepository.com/artifact/org.apache.activemq/activemq-spring -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-spring</artifactId>
<version>5.14.3</version>
</dependency>
Hope this can help others.

Onejar-maven-plugin to set the order of jar loading

I've been using the library apache-log4j-extras for logging. It contains class org.apache.log4j.Logger.
Now I had to reference some 3rd party library, that uses logback and has among its dependencies log4j-over-slf4j (jar). Unfortunately, latter jar also contains class org.apache.log4j.Logger.
Looks like the latter class is preferred by the onejar classloader...
I don't need logback and log4j-over-slf4j. Just want my org.apache.log4j.Logger from apache-log4j-extras back. What are my options with the Onejar-maven-plugin?
EDIT: It appeared to be an issue with Debug mode in IDEA, not with onejar. However the question is still relevant: how can I ensure that I load the requried class with Onejar?
EDIT2: E.g. in C# it could be easily resolved with "extern alias" feature.
why don't you just exclude it?
<dependency>
<groupId>my.naughty.thirdparty</groupId>
<artifactId>thirdparty-with-log4j-over-slf4j</artifactId>
<version>${thirdparty.version}</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
</exclusion>
</exclusions>
</dependency>
Looks like (for Debug mode in IDEA) just switching depenencies order solved the issue.
How it was:
<dependency>
<groupId>my.naughty.thirdparty</groupId>
<artifactId>thirdparty-ref-log4j-over-slf4j</artifactId>
<version>0.50</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>apache-log4j-extras</artifactId>
<version>1.1</version>
</dependency>
Changed to:
<dependency>
<groupId>log4j</groupId>
<artifactId>apache-log4j-extras</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>my.naughty.thirdparty</groupId>
<artifactId>thirdparty-ref-log4j-over-slf4j</artifactId>
<version>0.50</version>
</dependency>
But surely I can't consider it as a robust solution, especially for Onejar.

Dependency conflicts on maven

If I have some libs that have others dependencies in different versions like this example: commons-logging-1.0.4.jar (omitted for conflict with 1.1.1) and commons-logging-1.1.1.jar.
What´s the best practice about this, inform the exclusion of this conflict in the related dependency (by tag) or do nothing because the lib was omitted? Is there any problem don´t especify the exclusion of dependencies in the POM ?
Example that explain that how to resolve this in the POM, I´m putting the following instruction to resolve the internal conflicts about version:
<dependency>
<groupId>struts</groupId>
<artifactId>struts</artifactId>
<version>1.2.8</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
You need to configure a dependencyManagement section in your [parent] POM. This will coerce artifacts coming as transitive dependencies to be of the specified version.

Resources