Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I remove logback from a library's dependency while keeping SLF4J?

In my Vaadin project, I have a dependency on a certain library. This library uses slf4j for logging. In the library pom, logback slf4j binding is added as a runtime dependency.

    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>${logback.version}</version>
        <scope>runtime</scope>
    </dependency>

In my application, I directly use log4j for logging. I want the logs added by the library to go in my log4j log.

For this, I added following to my pom to include slf4j log4j binding

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.12</version>
    </dependency>

However, slf4j complains that it has found multiple bindings.

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/D:/program_files/apache-tomcat-8.0.24/temp/0-ROOT/WEB-INF/lib/logback-classic-1.0.13.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/D:/program_files/apache-tomcat-8.0.24/temp/0-ROOT/WEB-INF/lib/slf4j-log4j12-1.7.12.jar!/org/slf4j/impl/StaticLoggerBinder.class]

I checked the dependency tree of my application, which has following for its dependency on logback. (Following is the only dependency on logback)

[INFO] |  +- com.mycompany.mylib:libname:jar:1.1.0-SNAPSHOT:compile
[INFO] |  |  +- org.slf4j:jcl-over-slf4j:jar:1.7.5:runtime
[INFO] |  |  +- ch.qos.logback:logback-classic:jar:1.0.13:runtime
[INFO] |  |  |  \- ch.qos.logback:logback-core:jar:1.0.13:runtime
[INFO] |  |  +- ch.qos.logback:logback-access:jar:1.0.13:runtime

Also, when I checked inside WEB-INF\lib directory in my war file, I found following jars.

logback-access-1.0.13.jar
logback-classic-1.0.13.jar
logback-core-1.0.13.jar

Why did logback ended up in my lib directory? As I have heard, runtime dependencies should not come into libs directory.

How should I resolve this? The library is developed within my company and I can ask the library developers to remove the logback runtime dependencies if needed.

like image 577
Lahiru Chandima Avatar asked Aug 26 '15 16:08

Lahiru Chandima


People also ask

How do I disable Logback logging?

Logback does not allow logging to be disabled from the command line. However, if the configuration file allows it, you can set the level of loggers on the command line via a Java system property.

Is Logback deprecated?

Definitely not deprecated, but logback is generally an improvement, is a stable, mature lib, meshes better with SLF4J (which means no crazy classloader magic), so there's little reason to start a new project with log4j. For the record, Log4J development is deprecated.

What is SLF4J Logback?

Simple Logging Facade for Java (abbreviated SLF4J) acts as a facade for different logging frameworks (e.g., java. util. logging, logback, Log4j). It offers a generic API, making the logging independent of the actual implementation. This allows for different logging frameworks to coexist.


1 Answers

Option 1: They change their pom.

The easiest way to fix this would be to have the library developers in your own company mark logback as optional and require SLF4J as a compile dependency explicitly. This is the right, canonical way to do SLF4J in Maven. In other words:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>${slf4j.version}</version>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>${logback.version}</version>
    <scope>runtime</scope>
    <optional>true</optional>
</dependency>

Option 2: You revise their dependencies in your pom.

If you want to fix it yourself, without going through them, then you can use the exclusions tag when declaring their dependency. In other words, in your pom, do:

<dependency>
    <groupId>your.company</groupId>
    <artifactId>libraryname</artifactId>
    <version>${theirlibrary.version}</version>
    <exclusions>
        <exclusion>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
        </exclusion>
    </exclusions>
</dependency>

You asked if there's an reason to depend on Logback directly; generally there isn't, for a library author. Their pom configuration is probably just a minor oversight on their part. There are some reasons to depend on logback specifically, but they have to do with startup (stuff with JoranConfigurator or StatusPrinter, that sort of thing, which shouldn't come up with a library. Other reasons to call Logback classes directly include stuff like custom appenders, which, again, shouldn't come up in a library, only a deployed app.

like image 189
durron597 Avatar answered Sep 19 '22 08:09

durron597