Reputation: 22359
Trying to enable log4j
in SpringBoot + Gradle project is less common than Maven. So, here's the problem I'm facing:
gradle clean bootRun --stacktrace
:clean
:compileJava
:processResources
:classes
:findMainClass
:bootRun
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/home/mdesales/.m2/repository/org/slf4j/slf4j-log4j12/1.7.21/slf4j-log4j12-1.7.21.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/mdesales/.m2/repository/ch/qos/logback/logback-classic/1.1.7/logback-classic-1.1.7.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Detected both log4j-over-slf4j.jar AND bound slf4j-log4j12.jar on the class path, preempting StackOverflowError.
SLF4J: See also http://www.slf4j.org/codes.html#log4jDelegationLoop for more details.
Exception in thread "main" java.lang.ExceptionInInitializerError
Upvotes: 3
Views: 4056
Reputation: 22359
You can use the dependency resolution capability of Gradle to resolve which library version to load. One of the errors is about the version of Log4j to load, which were from 2 locations as shown in the error logs. So, for each of the name of the libraries, select which version should win.
The second piece to it is to completely exclude the dependencies to the spring-boot logging and logback classic, which are responsible for setting up the logging for SpringBoot by default. The following block helped with it.
configurations.all {
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
if (details.requested.name == 'log4j') {
details.useTarget 'log4j:log4j:1.2.+'
}
}
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
exclude group: 'org.springframework.boot', module: 'logback-classic'
}
Finally, the last change to add is the set of log4j
and slf4j
dependencies that will help you load the dependencies.
runtime group: 'org.slf4j', name: 'slf4j-api', version: '1.7.21'
runtime group: 'org.slf4j', name: 'jcl-over-slf4j', version: '1.7.21'
runtime group: 'org.slf4j', name: 'jul-to-slf4j', version: '1.7.21'
runtime group: 'org.slf4j', name: 'slf4j-log4j12', version: '1.7.21'
runtime group: 'log4j', name: 'log4j', version: '1.2.17'
Place it under the usual directory src/main/resources/
.
After those in place, I got what I needed: the logging output is different and using the properties on my log4j.xml.
$ SPRING_PROFILES_ACTIVE=dev gradle clean bootRun --stacktrace
:clean
:compileJava
:processResources
:classes
:findMainClass
:bootRun
2016-08-09 07:20:47,006 0 | INFO | context.annotation.AnnotationConfigApplicationContext.prepareRefresh#581 ["restartedMain" null] Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@15225245: startup date [Tue Aug 09 07:20:46 PDT 2016]; root of context hierarchy
2016-08-09 07:20:47,235 229 | INFO | internal.util.Version.<clinit>#30 ["background-preinit" null] HV000001: Hibernate Validator 5.2.4.Final
2016-08-09 07:20:47,440 434 | INFO | factory.annotation.AutowiredAnnotationBeanPostProcessor.<init>#155 ["restartedMain" null] JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
Upvotes: 3