Comments (15)
Aha #2, removing the exclusion we tried adding for one of the above problems finally fixed it.
So in summary, import the library before other log4j dependencies.
from log-captor.
Hi Derek,
Thank you for this detailed issue report! This is a typical SLF4J error message that is preventing to have more than one slf4j binding to be present at the classpath.
The log4j-to-slf4j
dependency within this library makes it possible to capture logs from apache when the end user is using apache log4j-core
while not using slf4j api/slf4j bridge/slf4j binder at all. This makes it convenient for those end-users to start without the need for additional configuration. Even if this library didn't included log4j-to-slf4j
you would still have a similar error. You can try it by excluding the specific library with the following snippet:
<dependency>
<groupId>io.github.hakky54</groupId>
<artifactId>logcaptor</artifactId>
<version>2.3.2</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
</exclusion>
</exclusions>
</dependency>
The main reason why this is happening is that your classpath already has a slf4j implementation and LogCaptor too. This is also mentioned here LogCaptor - Using Log Captor alongside with other logging libraries. So what you need to do is just exclude your slf4j implementation during the test phase. If you are using maven surefire or failsafe plugin you can add the following snippet to your pom:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<classpathDependencyExcludes>
<classpathDependencyExclude>org.apache.logging.log4j:log4j-slf4j-impl</classpathDependencyExclude>
</classpathDependencyExcludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<classpathDependencyExcludes>
<classpathDependencyExclude>org.apache.logging.log4j:log4j-slf4j-impl</classpathDependencyExclude>
</classpathDependencyExcludes>
</configuration>
</plugin>
</plugins>
</build>
This configuration is excluding your log4j-slf4j-impl
during the test-phase only. Can you give it a try and share your results here? I think excluding log4j-to-slf4j
from LogCaptor would not be needed.
I'm not sure if i'm applying the pom exclusions properly, but it seems like it might be easier to make a version that is compatible with org.apache.logging.log4j instead
I need to think about it. Thank you for the suggestion!
from log-captor.
Amazing, you found the solution. Interesting to see that the order of declaring the dependency in this specific use-case worked for you! I will note this solution down. Good luck asserting your log messages!
By the way I published here Java tutorials - LogCaptor isolated examples with different logging frameworks include this example and the adjustments to the pom which are included to get it working.
Update 14-07-2021
I noticed that you are using spring-boot-starter-log4j2
. This library has some transitive dependencies which indeed requires adjustments to your pom. I have added an example for this use case, see the example project here: https://github.com/Hakky54/java-tutorials/tree/main/log-captor-examples/log-captor-with-spring-boot-starter-log4j2
So you basically need to add the following configuration to your pom:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<classpathDependencyExcludes>
<classpathDependencyExclude>org.apache.logging.log4j:log4j-slf4j-impl</classpathDependencyExclude>
</classpathDependencyExcludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<classpathDependencyExcludes>
<classpathDependencyExclude>org.apache.logging.log4j:log4j-slf4j-impl</classpathDependencyExclude>
</classpathDependencyExcludes>
</configuration>
</plugin>
</plugins>
</build>
This will exclude org.apache.logging.log4j:log4j-slf4j-impl
from the classpath only during the test phase
I mentioned this solution also at the beginning of our conversation, see here: #6 (comment)
from log-captor.
The maven plugin changes don't seem to have any effect so far.
But changing to exclude log4j-to-slf4j
on your dependency gets me past the first error i was running into and gets me a little further to a casting exception:
java.lang.ClassCastException: class org.apache.logging.slf4j.Log4jLogger cannot be cast to class ch.qos.logback.classic.Logger (org.apache.logging.slf4j.Log4jLogger and ch.qos.logback.classic.Logger are in unnamed module of loader 'app')
at nl.altindag.log.LogCaptor.<init>(LogCaptor.java:49)
at nl.altindag.log.LogCaptor.forClass(LogCaptor.java:69)
at ....AddressTest.testAddressValidation(AddressTest.java:20)
from log-captor.
That is strange. It should have worked. Could you create a basic sample project on your GitHub repo so I can analyse your setup? In that way it would be much easier to reproduce it on my environment.
By the way I just tried it with a fresh new project to reproduce the same behaviour as wat you had. See here for the example project: GitHub - LogCaptor With Apache Log4j
This project contains:
- log4j-slf4j-impl
- LogCaptor
- JUnit
- AssertJ
And has the following plugin configuration:
- maven-compiler-plugin with
java 11
- maven-surefire-plugin with classpath dependency exclusion during the test phase for
org.apache.logging.log4j:log4j-slf4j-impl
With this setup it works as expected. The logs will be captured and I can assert those messages. It is also not needed to exclude log4j-to-slf4j
from logcaptor. Can you compare this setup with yours and share any difference or create a sample project which has the errors which you mentioned? That would make it much easier to analyse the root cause.
from log-captor.
Thanks for your help, the conflict must be some where in the larger project. I just don't understand how that would manifest inside LogCaptor. I'll try and trim down something i can share.
from log-captor.
since i'm still seeing this warning in the terminal, i'm guessing my issue is that something is still trying to use
org.apache.logging.slf4j.Log4jLogger
instead of ch.qos.logback.classic.Logger
. The stack trace message (org.apache.logging.slf4j.Log4jLogger and ch.qos.logback.classic.Logger are in unnamed module of loader 'app')
just doesn't help narrow that down at all.
SLF4J: Found binding in [jar:file:/home/derek/.m2/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.13.3/log4j-slf4j-impl-2.13.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/derek/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.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 [org.apache.logging.slf4j.Log4jLoggerFactory]
from log-captor.
This change to the existing POM file in the project seems to have yielded a passing test, pending further integration testing.
from log-captor.
Thank you for sharing the details, I think the log4j-slf4j-impl
is a transitive dependency so it could be indeed getting it from somewhere from any other dependency. You can track it down with the following command: mvn dependency:tree
Your issue with the logcaptor library is that log4j-slf4j-impl
dependency is somehow still present at the classpath during the test phase. I still think you don't need to exclude log4j-to-slf4j
and logback-classic
from logcaptor. We can also do some remote session through Ringcentral, Teamviewer, Discord or something else. In that way I might be able to help you a bit more. Let me know if your ok with that to go through it together
from log-captor.
My thinking was that excluding them from a test dependency in favour of an explicit dependency to replace the explicit dependency of log4j2
that was removed.
from log-captor.
Thats sounds reasonable but your application is still using org.apache.logging.log4j.LogManager
class in your code base. So excluding the apache logger library will prevent your project from compiling. So you are forced to add the library log4j-slf4j-impl
but if you also include logback-classic
library as you have shown in one of your previous messages you will get the same error which you got in your test when you will try to start your application.
I think your initial setup was good. I am assuming you only had log4j-slf4j-impl
and I think it should stay like that.
from log-captor.
Can you by the way share your pom configuration of the part which is running the unit tests? What are you using as a maven plugin to execute the unit tests?
from log-captor.
Thank you for sharing the details, I think the
log4j-slf4j-impl
is a transitive dependency so it could be indeed getting it from somewhere from any other dependency. You can track it down with the following command:mvn dependency:tree
Your issue with the logcaptor library is that
log4j-slf4j-impl
dependency is somehow still present at the classpath during the test phase.
[INFO] +- org.springframework.boot:spring-boot-starter-log4j2:jar:2.3.1.RELEASE:compile
[INFO] | +- org.apache.logging.log4j:log4j-slf4j-impl:jar:2.13.3:compile
[INFO] | | \- org.apache.logging.log4j:log4j-api:jar:2.13.3:compile
Well the existing spring-boot-starter-log4j2
is where log4j-slf4j-impl
is coming from. I can't seem to balance keeping that import so the production app isn't changed, and preventing further errors like i posted above with
java.lang.ClassCastException: class org.apache.logging.slf4j.Log4jLogger cannot be cast to class ch.qos.logback.classic.Logger (org.apache.logging.slf4j.Log4jLogger and ch.qos.logback.classic.Logger are in unnamed module of loader 'app')
at nl.altindag.log.LogCaptor.<init>(LogCaptor.java:49)
at nl.altindag.log.LogCaptor.forClass(LogCaptor.java:69)
at ....AddressTest.testAddressValidation(AddressTest.java:20)
from log-captor.
Aha, good to know which dependency is including log4j-slf4j-impl. So in the end it is still similar to the example project which I have created last week.
By the way. I am assuming you are using junit or any other framework for your tests. Do you know which maven plugin you are using to execute those tests? Most of the time surefire and failsafe maven plugins are used, so I am curious what you are using in your project.
from log-captor.
Running tests from Eclipse JUnit test runner plugin, and from the command line using maven surefire.
Good news, moving the LogCaptor dependency before spring-boot-starter-log4j2
seems to fix the error where org/slf4j/impl/StaticLoggerBinder.class
was being selected instead of org/slf4j/impl/StaticLoggerBinder.class
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/home/derek/.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:/home/derek/.m2/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.13.3/log4j-slf4j-impl-2.13.3.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]
�[1;31mERROR�[m 2021-02-04 18:55:42 ..dat.mod.Address --- Address is malformed.
But LogCaptor doesn't show any results now. I almost have a pruned down project to upload.
org.opentest4j.AssertionFailedError: Could not find expected error message in LogCapture ==> expected: <false> but was: <true>
at org.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:55)
at org.junit.jupiter.api.AssertFalse.assertFalse(AssertFalse.java:40)
at org.junit.jupiter.api.Assertions.assertFalse(Assertions.java:218)
at test.providius.datahub.AddressTest.testAddressValidation(AddressTest.java:30)
from log-captor.
Related Issues (20)
- Expose MDC logback property map in LogEvent HOT 4
- Add existing contributors HOT 11
- ConcurrentModificationException in getLogs() HOT 7
- Logcaptor error logs do not contain expected content when reusing instance HOT 7
- log4j HOT 1
- Running the unit test directly from IDEA gives error HOT 7
- Not working with org.jacoco:jacoco-maven-plugin HOT 6
- There appears to be a classloading problem when using LogCaptor with `@QuarkusTest` test classes HOT 2
- LogEvent should implement toString() HOT 4
- Not compatible with log4j2 2.17.2 HOT 5
- Allow to retrieve logs for custom log levels HOT 2
- consoleCaptor.getStandardOutput() doesn't work HOT 6
- Does this project target Log4J API 1.7? HOT 9
- spring-boot-starter + log-captor: log4j-slf4j-impl cannot be present with log4j-to-slf4j HOT 5
- Upgrade to 2.8.0 HOT 18
- Suppressing Console Output HOT 3
- Are we supposed to close LogCaptor at the end of a test? HOT 3
- Issue with custom levels HOT 3
- Seeing DEBUG level logs after adding logcaptor dependency HOT 2
- disableConsoleOutput() is throwing NPE HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from log-captor.