1. FIXING LOGGERFACTORY NOT A LOGBACK LOGGERCONTEXT BUT LOGBACK IS ON THE CLASSPATH, SPRING BOOT-COBERTURA ERROR
A few days ago I was working on a new Spring Boot web application where some dependencies version and common Maven plugins configuration were inherited from a parent pom. Everything was just fine, APIs would work as intended, Unit and IntegrationTests were passing except when generating the Cobertura code coverage report. It didn’t matter how minimalist this Spring Boot app could get, code coverage was just failing attempt after attempt.
This posts describes troubleshooting a Spring Boot application and Cobertura dependencies to fix multiple SLF4J bindings - found in the classpath - Failed to load ApplicationContext.
This snippet includes spring-boot-starter-log4j2 which transitively brings in slf4j1.7.x and log4j22.7. I have also included maven-surefire-plugin to run tests and cobertura-maven-plugin to report code coverage.
3. THE PROBLEM
presents when generating the cobertura code coverage report:
A partial output shows:
As mentioned earlier, even though the application runs as expected, tests passes when run in the IDE and when building the artifact from command line, but running the Maven goal cobertura:cobertura fails because two slf4j bindings are found in the classpath: logback-classic and log4j-slf4j-impl.
log4j-slf4j-impl is transitively included from spring-boot-starter-log4j2 which could be observed when looking at the output of the Maven goal dependency:tree but it doesn’t say much about logback-classic because it’s used by the CoberturaMaven plugin to instrument classes, run the tests and generate the report.
After some troubleshooting, this issue could be fixed by excluding logback-classic from the dependency including it, via Maven’s dependencyManagement section:
As the documentation states:
… libraries or frameworks should not declare a dependency on any SLF4J binding but only depend on slf4j-api …
Thanks for reading and as always, feedback is very much appreciated.
5. SOURCE CODE
Accompanying source code for this blog post can be found at: