11

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!

Simeon Yachev
  • 133
  • 2
  • 7
  • Does this answer your question? [Why am I getting a NoClassDefFoundError in Java?](https://stackoverflow.com/questions/34413/why-am-i-getting-a-noclassdeffounderror-in-java) – Danubian Sailor May 27 '22 at 12:25

1 Answers1

11

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>
Community
  • 1
  • 1
BlackC
  • 331
  • 3
  • 8
  • Commenting out the did nothing - I get the same exception. – Simeon Yachev Apr 14 '21 at 07:24
  • 1
    do you still depend on spring boot? if you want to use the versions 1.3.x of logback-classic ,omit spring boot. – BlackC Apr 14 '21 at 08:27
  • Great! It's all good now. I didn't realise that spring boot contains slf4j/Logback and I don't need their dependencies. I removed them now and I'm left with the spring boot starter dependencies only, which are enough. Thanks a lot! – Simeon Yachev Apr 14 '21 at 09:57
  • @BlackC What exactly do you mean by "depend on spring boot" if the spring boot starter dependencies are still allowed? I ask as I am seeing the same issue and trying to keep the starter dependencies like Simeon. – FreakyDan Jan 27 '23 at 19:00
  • 2
    I'm not sure what versions of boot 2.x this affects, but as of 2.7.8 spring docs say logback is configured to work by default with "starters" for console output. Optional file output can be added. https://docs.spring.io/spring-boot/docs/2.7.8/reference/html/features.html#features.logging – IchBin Jan 27 '23 at 23:14
  • 1
    Spring default log component is logback,When you import spring and logbck at the same time in pom.xml. there are multi version logbck. maybe exist version compatibility. – BlackC Jan 28 '23 at 08:40
  • 1
    Went for spring boots default logback dependencies, fixed issue with conflicting StaticLoggerBinder implemenations of two different pom's... – solujic Jan 30 '23 at 12:20