SLF4J Logback LoggerContext Conflicts - java

I am working on deploying a spring boot executable jar for my application. Im using SLF4J logging, and when I build and run inside of IntelliJ I have no issues.
However, when I try to run the .jar, from the command line I get a LoggerFactory is not a Logback LoggerContext but Logback is on the classpath exception.
It complains about the slf4j-log4j12-1.7.12.jar in two places /opt/mapr/lib/ and /opt/mapr/hadoop/hadoop-2.7.0/share/hadoop/common/lib/.
If i remove the jar from both places and run my app:
java -cp $(mapr classpath):MapRProducerApp-0.0.1-SNAPSHOT.jar org.springframework.boot.loader.PropertiesLauncher
it will then fail startup due to SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
I dont understand why it would fail saying faild to load the slf4j class when my apps .jar is built with that dependency through
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
In IntelliJ, I am bringing in all external dependencies that exist inside the /opt/mapr/lib folder, which includes the slf4j-log4j12-1.7.10.jar, but IntelliJ does not give the Logback LoggerContext error.
To recap here:
Building and running the jar on its own works, but will fail because it needs dependencies that exist inside the mapr classpath.
Running the jar with the mapr classpath fails because of the slf4j jar inside /opt/mapr/lib.
Removing that jar leads to another failure about a slf4j jar in /opt/mapr/hadoop/hadoop-2.7.0/share/hadoop/common/lib/.
Removing that jar then fails the app because it now cannot find any slf4j binding.
Is there something im missing? Do I need to package my app a certain way so it does not include the SLF4J dependency?

I'm not clear about your <dependencies> hierarchy, but by adding <exclusion> you can simply resolve the conflict.
<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>

If you are using Spring-boot actuator, only exclusion of spring-logging might not help.
You will have to provide logging for it. Spring Boot support log4j for logging configuration.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<exclusions>
<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>
</dependency>
Refrence: https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto.logging

Related

Project inside SpringBoot 2.6.0 working, forced to use Log4J1 and JCL redirect working but JUL not

I have a project whereby the latest build is now SpringBoot 2.6.0 (and older one is a WAR for Tomcat 8). I have a sub-project/component that connects to stuff that forces me to use Log4J1. Logback was working beautifully but I've had to disable it (due to Log4J2 eclipsing and breaking the code that requires Log4J1 and also a new vendor component requiring Log4J2 as well).
I've:
disabled Logback by excluding spring-boot-starter-logging
Added a dependency for spring-boot-starter-log4j
Via the Dependency hierarchy tab (in Eclipse) I can see the jcl and jul libraries and in my logs (Console and File appenders) it is clear that SpringBoot (jcl stuff) and any of my project jcl calls are logged, but any JUL are not.
I've read tons of different tickets on here, gleaned together the info and got to this point. So it's all good except I cannot seem to pipe the JUL calls to the Log4J1 setup.
I can see jul-to-slf4j brought in via spring-boot-starter-log4j.
I thought I'd write here as I'm sure it's something simple I've missed but I think I've been staring at it for too long this afternoon! :)
What have I missed?
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<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-log4j</artifactId>
<version>1.3.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.32</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.32</version>
</dependency>
I got the JUL bits piping via adding this:
SLF4JBridgeHandler.install();
java.util.logging.LogManager.getLogManager().getLogger("").setLevel( Level.INFO);
Which I found on question JUL to SLF4J Bridge

unable to deploy spring boot app on tomcat [duplicate]

This question already has answers here:
Servlet 5.0 JAR throws compile error on javax.servlet.* but Servlet 4.0 JAR does not
(3 answers)
Deploying Spring 5.x on Tomcat 10.x
(1 answer)
Closed 1 year ago.
I was trying to deploy spring boot micro-service on the tomcat server but was unable to get any response. The url was showing 404 error then I decided to go from very basic so I created a simple spring boot project with Spring Boot Initializer. There I choose
war as packaging.
java version 16 (as I only have this on my machine).
Added Spring Web dependency.
With this setting spring initializer automatically added necessary stuff like war packaging, tomcat dependency, spring web dependency and also created ServletInitializer class for me.
After that I opened the downloading project in netbeans 12 and made just a few changes i.e.
Added main class in the pom.xml file with <start-class> tag and annotated main class with #RestController and exposed 1 endpoint which return simple string.
Then from the project's main folder I ran the command mvn package also tried mvn clean install as deployment with the 1st command was unsuccessful.
Here are my configuration
Environment Variables:
System Variables
CATALINA_HOME: D:\Inzimam Tariq\apache-tomcat-10.0.10.
JAVA_HOME: C:\Program Files\Java\jdk-16.0.2
Relevent values in Path Variable: C:\Program Files\Common Files\Oracle\Java\javapath, D:\Inzimam Tariq\apache-maven-3.8.2\bin, and C:\Program Files\Java\jdk-16.0.2\bin.
User Variable
MAVEN_HOME: D:\Inzimam Tariq\apache-maven-3.8.2\bin.
I'm using windows 10 64-bit. Tomcat manager shows the app as deployed but when I click on that it shows 404. My JDK folder does not show JRE folder so I searched over internet and found that Java does not include JRE now. I also tried to rename my war file to the project name as some articles suggested that i.e. abc.war from abc-0.0.1-SNAPSHOT but still error is the same.
Please can someone point me to the right direction? Regards
After Deploying your project war file in Tomcat, try to make the following changes in your POM.xml file. Then restart your tomcat. Probably it will work.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<exclusion>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>

SLF4J + version 1.7.x by your slf4j binding is not compatible 1.6 [duplicate]

I realised that one of my projects uses slf4j 1.5.8 and Hibernate uses slf4j 1.6. While building with Maven it downloads both jars but I guess the class files of 1.5.8 are used. So, when I run the program i get following error:
SLF4J: The requested version 1.5.8 by your slf4j binding is not compatible with [1.6]
In pom.xml I have put
<dependencyManagement>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.1</version>
</dependency>
</dependencyManagement>
The 1.5.8 is part of dependency so it's downloaded on its own.
As you discovered yourself, there are two libraries (Hibernate and some other) transitively importing SLF4J in two different versions. Unfortunately the older version is being picked up by maven (there are some rules which dependency should be chosen by maven in this situation). The solution is to add the exclusion in the dependency that imports older version of SLF4J (com.example:foo-bar is example here):
<dependency>
<groupId>com.example</groupId>
<artifactId>foo-bar</artifactId>
<version>1.2.3</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
If you still experience this problem, issue:
$ mvn dependency:tree
Look for 1.5.8 version and exclude it from all libraries importing it.
Excluding is quite unnecessary and maybe quite misleading. Instead, explicitly include the slf4j-api with the desired version in your projects pom file. That's it!
This approach takes advantage of Maven's transitivity rules: the nearest dependency declaration wins.
you can exclude the wrong version with something like this:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.2.7.ga</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>

Class path contains multiple SLF4J bindings

I tried to debug my project but got this
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/usr/local/storm/lib/logback-classic-1.0.13.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/user/.m2/repository/ch/qos/logback/logback-classic/1.0.13/logback-classic-1.0.13.jar!/org/slf4j/impl/StaticLoggerBinder.class]
what should i do ?
i haven't any dependency for SLF4J in POM just this
<dependency>
<groupId>org.apache.storm</groupId>
<artifactId>storm-core</artifactId>
<version>0.9.6</version>
<scope>provided</scope>
</dependency>
i tried to use the solutions i found in similar posts but didn't solve it ! like
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>logback-classic</groupId>
<artifactId>ch.qos.logback</artifactId>
</exclusion>
</exclusions>
I tried to replace provided to compile but didn't solve it too .
I got this with using mvn dependency:tree
org.slf4j:log4j-over-slf4j:jar:1.6.6:provided
org.slf4j:slf4j-api:jar:1.7.5:compile
You have 2 sources of dependencies for storm one from /usr/local/storm/lib/ directory and the second from maven which cause multiple binding for sl4j.
Try using just one source of dependencies.
Following the line of the accepted answer, the way i found to try using just one source of dependencies, was to clone/create again the project i was working on. In my case was an already started project and probably due to poor connection speed, i had a few issues re importing all Maven Projects. So i messed up a bit with the project's settings trying to access all the propper dependencies.
That caused some unexpected changes on my project's pom.xml file that leaded to the error. So, cloning again de project to a new folder and making the maven re import with some decent internet speed just worked fine for me.
Hope to be helpful. Regards

Add dependecy to Maven and set to $CATALINA_HOME/shared/lib

I'm using Matlab MCR in web project so I imported these dependecies to pom.xml
<!-- Matlab client tool library -->
<!-- <dependency>
<groupId>DataConcatenation</groupId>
<artifactId>DataConcatenation</artifactId>
<version>0.0.5-SNAPSHOT</version>
</dependency> -->
<!-- <dependency>
<groupId>DataConcatenator</groupId>
<artifactId>DataConcatenator</artifactId>
<version>0.0.5-SNAPSHOT</version>
</dependency> -->
<!-- <dependency>
<groupId>DataConversion</groupId>
<artifactId>DataConversion</artifactId>
<version>0.0.5-SNAPSHOT</version>
</dependency> -->
<dependency>
<groupId>DataConverter</groupId>
<artifactId>DataConverter</artifactId>
<version>0.0.5-SNAPSHOT</version>
<exclusions>
<exclusion>
<artifactId>DataConcatenation</artifactId>
<groupId>DataConcatenation</groupId>
</exclusion>
<exclusion>
<artifactId>DataConcatenator</artifactId>
<groupId>DataConcatenator</groupId>
</exclusion>
<exclusion>
<artifactId>DataConversion</artifactId>
<groupId>DataConversion</groupId>
</exclusion>
</exclusions>
</dependency>
The first problems is that I have to exclude the other tree dependencies even if I use only DataConverter, But I need only dataConverter and this library doesn't have other dependecies.
The second and most important problem is this error:
Threw exception in ZipAndMat::createZipAndMat: java.lang.UnsatisfiedLinkError: Native Library /usr/v81/bin/glnxa64/libnativedl.so already loaded in another classloader
I read a lot of guide and I understand that I have to put this jar into $CATALINA_HOME/shared/lib so all the class loader share the same jar.
But how can I add this dependecy to the above path? This is the first time that I have to implement this configuration. I use tomcat on my server and deploy project through war file.
Thanks
You can place the jar into $CATALINA_HOME/shared/lib, and then specify in your POM the dependency's <scope> as provided:
<dependency>
<groupId>DataConverter</groupId>
<artifactId>DataConverter</artifactId>
<version>0.0.5-SNAPSHOT</version>
<scope>provided</scope>
<exclusions>
...
</exclusions>
</dependency>
This method is often used for jars which contain JDBC drivers when running on Tomcat; the jdbc jar is placed in $CATALINA_HOME/shared/lib (so all WARs can find it), yet each project list’s the JDBC jar as a dependency with provided as the scope.
See this post for more information on provided.

Categories

Resources