javalogbackslf4jnoclassdeffounderrorspring-logback

SLF4J with Logback: NoClassDefFoundError: org/slf4j/impl/StaticLoggerBinder


I'm trying to implement a RollingFile Logger using SLF4J and Logback in particular, but I'm stuck with an exception, that I can't resolve. Here it is:

Exception in thread "main" java.lang.NoClassDefFoundError: org/slf4j/impl/StaticLoggerBinder
    at org.springframework.boot.logging.logback.LogbackLoggingSystem.getLoggerContext(LogbackLoggingSystem.java:293)
    at org.springframework.boot.logging.logback.LogbackLoggingSystem.beforeInitialize(LogbackLoggingSystem.java:118)
    at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationStartingEvent(LoggingApplicationListener.java:232)
    at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:213)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:131)
    at org.springframework.boot.context.event.EventPublishingRunListener.starting(EventPublishingRunListener.java:76)
    at org.springframework.boot.SpringApplicationRunListeners.lambda$starting$0(SpringApplicationRunListeners.java:53)
    at java.util.ArrayList.forEach(ArrayList.java:1259)
    at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:117)
    at org.springframework.boot.SpringApplicationRunListeners.starting(SpringApplicationRunListeners.java:53)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:317)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1313)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302)
    at com.upnetix.java.simeonyachev.PlexUserNameApplication.main(PlexUserNameApplication.java:13)
Caused by: java.lang.ClassNotFoundException: org.slf4j.impl.StaticLoggerBinder
    at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
    ... 17 more

That is my pom.xml :

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.4</version>
        <relativePath/>
    </parent>

    <dependencies>
        <!--SPRING BOOT-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
<!--            <exclusions>-->
<!--                <exclusion>-->
<!--                    <groupId>org.apache.logging.log4j</groupId>-->
<!--                    <artifactId>log4j-to-slf4j</artifactId>-->
<!--                </exclusion>-->
<!--                <exclusion>-->
<!--                    <groupId>org.apache.logging.log4j</groupId>-->
<!--                    <artifactId>log4j-api</artifactId>-->
<!--                </exclusion>-->
<!--                <exclusion>-->
<!--                    <groupId>org.slf4j</groupId>-->
<!--                    <artifactId>jul-to-slf4j</artifactId>-->
<!--                </exclusion>-->
<!--            </exclusions>-->
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.2.4.RELEASE</version>
<!--            <exclusions>-->
<!--                <exclusion>-->
<!--                    <groupId>org.jboss.logging</groupId>-->
<!--                    <artifactId>jboss-logging</artifactId>-->
<!--                </exclusion>-->
<!--            </exclusions>-->
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>2.2.4.RELEASE</version>
            <scope>test</scope>
        </dependency>

        <!-- LOGBACK -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>2.0.0-alpha1</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.3.0-alpha5</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.3.0-alpha5</version>
        </dependency>
    </dependencies>

I'm not even sure if I need the exclusions, but I've tried starting my application both ways and that didn't solve the problem.

And that is my logback.xml:

<configuration>
<property name="LOGS" value="./logs"/>

<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${LOGS}/logFile.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
        <fileNamePattern>${LOGS}/logFile%i.log</fileNamePattern>
        <minIndex>1</minIndex>
        <maxIndex>20</maxIndex>
    </rollingPolicy>
    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
        <maxFileSize>10MB</maxFileSize>
    </triggeringPolicy>
    <encoder>
        <pattern>%date %-5level --- [%thread] - %-50logger{40} : %message %ex{short} %n</pattern>
    </encoder>
</appender>

<logger name="com.java.simeon" level="INFO">
    <appender-ref ref="FILE"/>
</logger>

<root level="INFO">
    <appender-ref ref="FILE" />
</root>

I did a thorough research into the topic and found that StaticLoggerBinder is not being used since the release of slf4j-api.1.8.x and onwards. As per the official slf4j site(here and here), using the latest versions of slf4j-api(2.x.x) and logback-classic(1.3.x) should do the work(by using a new ServiceLoader mechanism and removing the need of StaticLoggerBinder).

I've tried using older versions of slf4j-api and logback-classic, but with no success.

The question is why does my program need StaticLoggerBinder and throw an exception about it when I'm using the newest slf4j-api and logback-classic versions which shouldn't care about it?

Any suggestions on how to solve the problem would be appreciated!


Solution

  • Because you are using version 2.4.4 of spring-boot-starter-parent. Spring Boot uses StaticLoggerBinder to get the log factory. StaticLoggerBinder has been deleted in version 1.3.x of logback-classic. Here are two ways to solve this problem:

    1. Use versions of slf4j-api (2.x.x) and logback-classic (1.3.x) without Spring Boot.
    2. Use Spring Boot's default logback dependencies.
        <dependencies>
            <!-- omit spring boot -->
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
                <version>2.0.0-alpha1</version>
            </dependency>
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-classic</artifactId>
                <version>1.3.0-alpha5</version>
            </dependency>
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-core</artifactId>
                <version>1.3.0-alpha5</version>
            </dependency>
        </dependencies>