Upgrading from spring-boot 3.1.6 to 3.2.1 seems to resurface issue #37484

Steps to reproduce:

  • Run tests in the attached gradle projects (currently configured with spring-boot 3.1.6), tests pass. The test literally just starts the container, no actual functionality is tested.

  • Change the spring-boot version to 3.2.0 or 3.2.1 and run the tests again. This time they fail with a conflict between slf4j and logback. spring-boot-3.2.1-issue.zip

Comment From: wilkinsona

Thanks for the sample. This is not the same error as #37484 where the problem was with org.slf4j.helpers.SubstituteLoggerFactory. In this case, it's org.apache.logging.slf4j.Log4jLoggerFactory that is causing the problem:

Caused by: java.lang.IllegalArgumentException: LoggerFactory is not a Logback LoggerContext but Logback is on the classpath. Either remove Logback or the competing implementation (class org.apache.logging.slf4j.Log4jLoggerFactory loaded from file:/Users/awilkinson/.gradle/caches/modules-2/files-2.1/org.apache.logging.log4j/log4j-slf4j2-impl/2.21.1/77d14bb4ef6487833652c443dd7d264e26e2e968/log4j-slf4j2-impl-2.21.1.jar). If you are using WebLogic you will need to add 'org.slf4j' to prefer-application-packages in WEB-INF/weblogic.xml: org.apache.logging.slf4j.Log4jLoggerFactory
    at org.springframework.util.Assert.instanceCheckFailed(Assert.java:592)
    at org.springframework.util.Assert.isInstanceOf(Assert.java:511)
    at org.springframework.boot.logging.logback.LogbackLoggingSystem.getLoggerContext(LogbackLoggingSystem.java:396)
    at org.springframework.boot.logging.logback.LogbackLoggingSystem.beforeInitialize(LogbackLoggingSystem.java:124)
    at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationStartingEvent(LoggingApplicationListener.java:238)
    at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:220)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:178)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:171)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:149)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:137)
    at org.springframework.boot.context.event.EventPublishingRunListener.multicastInitialEvent(EventPublishingRunListener.java:136)
    at org.springframework.boot.context.event.EventPublishingRunListener.starting(EventPublishingRunListener.java:75)
    at org.springframework.boot.SpringApplicationRunListeners.lambda$starting$0(SpringApplicationRunListeners.java:54)
    at java.base/java.lang.Iterable.forEach(Iterable.java:75)
    at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:118)
    at org.springframework.boot.SpringApplicationRunListeners.starting(SpringApplicationRunListeners.java:54)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:326)
    at org.springframework.boot.test.context.SpringBootContextLoader.lambda$loadContext$3(SpringBootContextLoader.java:137)
    at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:58)
    at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:46)
    at org.springframework.boot.SpringApplication.withHook(SpringApplication.java:1458)
    at org.springframework.boot.test.context.SpringBootContextLoader$ContextLoaderHook.run(SpringBootContextLoader.java:552)
    at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:137)
    at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:108)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:225)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:152)
    ... 17 more

The problem's due to spring-kafka-test depending on Zookeeper which depends on Logback:

\--- org.springframework.kafka:spring-kafka-test:3.0.12
     +--- com.google.code.findbugs:jsr305:3.0.2
     +--- org.springframework:spring-context:6.0.13 -> 6.1.2 (*)
     +--- org.springframework:spring-test:6.0.13 -> 6.1.2 (*)
     +--- org.springframework.retry:spring-retry:2.0.2 -> 2.0.5
     +--- org.apache.zookeeper:zookeeper:3.6.3 -> 3.8.3
     |    +--- org.apache.zookeeper:zookeeper-jute:3.8.3
     |    |    \--- org.apache.yetus:audience-annotations:0.12.0
     |    +--- org.apache.yetus:audience-annotations:0.12.0
     |    +--- io.netty:netty-handler:4.1.94.Final -> 4.1.104.Final (*)
     |    +--- io.netty:netty-transport-native-epoll:4.1.94.Final -> 4.1.104.Final (*)
     |    +--- org.slf4j:slf4j-api:1.7.30 -> 2.0.9
     |    +--- ch.qos.logback:logback-core:1.2.10 -> 1.4.14
     |    +--- ch.qos.logback:logback-classic:1.2.10 -> 1.4.14
     |    |    +--- ch.qos.logback:logback-core:1.4.14
     |    |    \--- org.slf4j:slf4j-api:2.0.7 -> 2.0.9

I suspect that Zookeeper doesn't need Logback at runtime and only requires SLF4J plus a logging framework that's bound to SLF4J. The tests in the sample pass when excluding Logback as well as Boot's logging starter:

configurations {
    all {
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
        exclude group: 'ch.qos.logback'
    }
}

You may want to open a Spring Kafka to explore excluding Logback from spring-kafka-test's org.apache.zookeeper:zookeeper dependency.