Marcello DeSales
Marcello DeSales

Reputation: 22359

How to enable Log4j on SpringBoot Gradle: log4j-over-slf4j.jar, slf4j-log4j12.jar Multiple Bindings

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

Questions

Upvotes: 3

Views: 4056

Answers (1)

Marcello DeSales
Marcello DeSales

Reputation: 22359

Gradle Dependency Resolution

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'
}

Log4j Dependencies

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'

log4j.xml

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

Related Questions