java.lang.ClassCastException: org.slf4j.impl.Slf4jLoggerFactory cannot be cast to ch.qos.logback.classic.LoggerContext is thrown when updating to JBoss EAP 7.4 from an older minor version

Solution Verified - Updated -

Environment

  • Red Hat JBoss Enterprise Application Platform (EAP)
    • 7.4

Issue

When migrating to JBoss EAP 7.4 from an older minor version, deployment fails with the following exception. Deployment completed successfully without errors in JBoss EAP 7.3:

14:06:26,349 ERROR [stderr] (ServerService Thread Pool -- 75) SLF4J: Class path contains multiple SLF4J bindings.
14:06:26,350 ERROR [stderr] (ServerService Thread Pool -- 75) SLF4J: Found binding in [jar:file:/opt/jboss-eap-7.4/modules/system/layers/base/org/slf4j/impl/main/slf4j-jboss-logmanager-1.1.0.Final-redhat-00001.jar!/org/slf4j/impl/StaticLoggerBinder.class]
14:06:26,350 ERROR [stderr] (ServerService Thread Pool -- 75) SLF4J: Found binding in [vfs:/content/testapp.war/WEB-INF/lib/logback-classic-1.2.11.jar/org/slf4j/impl/StaticLoggerBinder.class]
14:06:26,350 ERROR [stderr] (ServerService Thread Pool -- 75) SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
14:06:26,350 ERROR [stderr] (ServerService Thread Pool -- 75) SLF4J: Actual binding is of type [org.slf4j.impl.Slf4jLoggerFactory]
14:06:26,361 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 75) MSC000001: Failed to start service jboss.deployment.unit."testapp.war".undertow-deployment: org.jboss.msc.service.StartException in service jboss.deployment.unit."testapp.war".undertow-deployment: java.lang.RuntimeException: java.lang.ClassCastException: org.slf4j.impl.Slf4jLoggerFactory cannot be cast to ch.qos.logback.classic.LoggerContext
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentService$1.run(UndertowDeploymentService.java:81)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
    at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1990)
    at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
    at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
    at java.lang.Thread.run(Thread.java:750)
    at org.jboss.threads.JBossThread.run(JBossThread.java:513)
Caused by: java.lang.RuntimeException: java.lang.ClassCastException: org.slf4j.impl.Slf4jLoggerFactory cannot be cast to ch.qos.logback.classic.LoggerContext
    at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:257)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentService.startContext(UndertowDeploymentService.java:96)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentService$1.run(UndertowDeploymentService.java:78)
    ... 8 more
Caused by: java.lang.ClassCastException: org.slf4j.impl.Slf4jLoggerFactory cannot be cast to ch.qos.logback.classic.LoggerContext
    at sample.servlet.StartupListener.contextInitialized(StartupListener.java:19)
    at io.undertow.servlet.core.ApplicationListeners.contextInitialized(ApplicationListeners.java:187)
    at io.undertow.servlet.core.DeploymentManagerImpl$1.call(DeploymentManagerImpl.java:219)
    at io.undertow.servlet.core.DeploymentManagerImpl$1.call(DeploymentManagerImpl.java:187)
    at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:42)
    at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
    at org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction.lambda$create$0(SecurityContextThreadSetupAction.java:105)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1551)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1551)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1551)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1551)
    at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:255)
    ... 10 more

The application contains slf4j and logback jar files as follows:

.
├── META-INF
│   ├── MANIFEST.MF
│   └── maven
│       └── sample
│           └── logback
│               ├── pom.properties
│               └── pom.xml
└── WEB-INF
    ├── classes
    │   ├── logback.xml
    │   └── sample
    │       └── servlet
    │           ├── EchoServlet.class
    │           └── StartupListener.class
    ├── jboss-deployment-structure.xml
    └── lib
        ├── logback-classic-1.2.11.jar
        ├── logback-core-1.2.11.jar
        └── slf4j-api-1.7.36.jar

The following jboss-deployment-structure.xml has been added to WEB-INF/jboss-deployment-structure.xml to disable implicit dependencies to the logging libraries:

<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
    <deployment>
        <exclusions>
            <module name="org.jboss.logging"/>
            <module name="org.apache.commons.logging"/>
            <module name="org.apache.log4j"/>
            <module name="org.slf4j"/>
            <module name="org.jboss.logging.jul-to-slf4j-stub"/>
        </exclusions>
    </deployment>
</jboss-deployment-structure>

Resolution

Applications that are packaging a logging framework and not wanting to use the EAP logging APIs, should use excluded-subsystem and exclude the logging subsystem as shown in this article and then you do not have to exclude all of the individual logging modules as shown below.

Add module org.slf4j.impl to jboss-deployment-structure.xml as a module to be excluded:

<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
    <deployment>
        <exclusions>
            <module name="org.jboss.logging"/>
            <module name="org.apache.commons.logging"/>
            <module name="org.apache.log4j"/>
            <module name="org.slf4j"/>
            <module name="org.slf4j.impl"/>    <<<=== add this line in JBoss EAP 7.4.0 or later
            <module name="org.jboss.logging.jul-to-slf4j-stub"/>
        </exclusions>
    </deployment>
</jboss-deployment-structure>

Related Solutions

Root Cause

org.slf4j.impl module has been added to default Implicit Module Dependencies by WFCORE-482(commit) fixed in JBoss EAP 7.4.0. The following logging-related modules have been added since 7.4.0:

  • org.jboss.logmanager
  • org.slf4j.ext
  • org.slf4j.impl
  • org.apache.logging.log4j.api

Diagnostic Steps

Logging implicit dependencies added to the application can be checked in TRACE level logs of org.jboss.as.logging Logger:

standalone.xml

            <logger category="sun.rmi">
                <level name="WARN"/>
            </logger>
            <logger category="org.jboss.as.logging">   <<<===
                <level name="TRACE"/>                  <<<===
            </logger>                                  <<<===
            <root-logger>
                <level name="INFO"/>

Example logs in EAP 7.4:

20:12:14,399 TRACE [org.jboss.as.logging] (MSC service thread 1-6) Adding module 'org.apache.commons.logging' to deployment 'logback.war'
20:12:14,400 TRACE [org.jboss.as.logging] (MSC service thread 1-6) Adding module 'org.apache.log4j' to deployment 'logback.war'
20:12:14,400 TRACE [org.jboss.as.logging] (MSC service thread 1-6) Adding module 'org.apache.logging.log4j.api' to deployment 'logback.war'
20:12:14,400 TRACE [org.jboss.as.logging] (MSC service thread 1-6) Adding module 'org.jboss.logging' to deployment 'logback.war'
20:12:14,400 TRACE [org.jboss.as.logging] (MSC service thread 1-6) Adding module 'org.jboss.logging.jul-to-slf4j-stub' to deployment 'logback.war'
20:12:14,400 TRACE [org.jboss.as.logging] (MSC service thread 1-6) Adding module 'org.jboss.logmanager' to deployment 'logback.war'
20:12:14,400 TRACE [org.jboss.as.logging] (MSC service thread 1-6) Adding module 'org.slf4j' to deployment 'logback.war'
20:12:14,401 TRACE [org.jboss.as.logging] (MSC service thread 1-6) Adding module 'org.slf4j.ext' to deployment 'logback.war'
20:12:14,401 TRACE [org.jboss.as.logging] (MSC service thread 1-6) Adding module 'org.slf4j.impl' to deployment 'logback.war'

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.

Comments