Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SLF4J: multiple SLF4J bindings with Gradle Plugin

I know its a common issue to have the issue with SLF4J: Class path contains multiple SLF4J bindings.

SLF4J: Found binding in [jar:file:/C:/Users/<name>/.gradle/caches/4.9/generated-gradle-jars/gradle-api-4.9.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/C:/Users/<name>/.gradle/caches/modules-2/files-2.1/org.apache.logging.log4j/log4j-slf4j-impl/2.2/afd596adf5086b4f4746254b25a3a4b513f1d6e4/log4j-slf4j-impl-2.2.jar!/org/slf4j/impl/StaticLoggerBinder.class]

I'm getting this error when I run a gradle build and I have applied the gradle-plugin plugin e.g. class with

import org.gradle.api.*
class CommonTestPlugin implements Plugin<Project> {

and in gradle

apply plugin: 'java-gradle-plugin'  

I'm using that plugin so I can add code to create a plugin.

The error above seems to point to gradle-api as the offending dependency but I when I fired up the dependency-insight task with dependencyInsight --dependency gradle-api

it returned:

No dependencies matching given input were found in configuration ':compileClasspath'

My question is: how can I determine how to define/exclude dependency that the plugin is using? Im using things like the following, I just can't figure out how to apply that to the plugin-api

compile (group: 'com.aestasit.infrastructure.sshoogr', name: 'sshoogr', version: '0.9.26'){
    // exclude this to stop warnings about multiple SLF4J bindings.
    exclude group: 'ch.qos.logback', module: 'logback-classic'
}
like image 895
Andy Dingfelder Avatar asked Aug 02 '18 02:08

Andy Dingfelder


People also ask

What are SLF4J bindings?

Bindings are basically implementations of a particular SLF4J class meant to be extended to plug in a specific logging framework. By design, SLF4J will only bind with one logging framework at a time. Consequently, if more than one binding is present on the classpath, it will emit a warning.

How do I know if SLF4J is binding?

Put a breakpoint on .. say.. LOG.info(...). Once debugger stops there, step into.. and viola.. you will find yourself in the code of the actual logger... say log4j or logback..

Does your class path contains multiple SLF4J bindings?

You should not get SLF4J Warning: Class Path Contains Multiple SLF4J Bindings now. SLF4J: class path contains multiple SLF4J bindings. That’s all about SLF4J: Class Path Contains Multiple SLF4J Bindings.

How does SLF4J choose a logging framework to use?

If SLF4J finds multiple bindings, it will pick one logging framework from the list and bind with it. As can be seen on the last line of the warning, SLF4J has chosen Log4j by using org.slf4j.impl.Log4jLoggerFactory for the actual binding.

How do I find and resolve SLF4J Classpath conflicts in Gradle?

Find SLF4J classpath conflicts at build time using Gradle dependency capabilities Identifies conflicts and enables resolving them for logger implementations in the JVM logging ecosystem Library supporting JSON-logging for Logback.

Should I use SLF4J for embedded components?

It is worth noting that embedded components such as libraries or frameworks should never declare a dependency on any SLF4J binding. This is because when a library declares a compile-time dependency on an SLF4J binding, it imposes that binding on the end-user. Obviously, this negates SLF4J's basic purpose.


1 Answers

I've hit the same problem. The workaround I've found so far is a brutal exclusion from the target JAR being built:

bootJar{
  exclude('gradle-api-*.jar', 'groovy-*.jar')
}

I'm using Spring boot plugin. bootJar extends jar task.

The question remains, though: do all the users of a plugin must do this kind of exclusion hocus-pocus in order to get it to work?

like image 147
badbishop Avatar answered Oct 05 '22 23:10

badbishop