Hi. I get the exception when try to replace logging module with log4j2 in spring boot version 2.5.1. This error doesn't occur in 2.4.7 and below.
Exception in thread "SpringApplicationShutdownHook" java.lang.ClassCastException: org.apache.logging.log4j.simple.SimpleLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext
at org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.getLoggerContext(Log4J2LoggingSystem.java:329)
at org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.lambda$getShutdownHandler$2(Log4J2LoggingSystem.java:304)
at java.lang.Iterable.forEach(Iterable.java:75)
at org.springframework.boot.SpringApplicationShutdownHook.run(SpringApplicationShutdownHook.java:102)
at java.lang.Thread.run(Thread.java:748)
I also tried to downgrade log4j to 2.13.x, but it didn't help.
Dependencies
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.springframework.boot") version "2.5.1"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
kotlin("jvm") version "1.5.10"
kotlin("plugin.spring") version "1.5.10"
id("com.google.protobuf") version "0.8.16"
id("idea")
}
group = "some.package"
version = "1.0.0-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_1_8
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("org.springframework.boot:spring-boot-starter-data-r2dbc")
implementation("org.springframework.boot:spring-boot-starter-oauth2-client")
implementation("org.springframework.boot:spring-boot-starter-rsocket")
implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.springframework.boot:spring-boot-starter-validation")
implementation("org.springframework.boot:spring-boot-starter-webflux")
implementation("org.springframework.boot:spring-boot-starter-log4j2")
implementation("org.springframework.security:spring-security-messaging")
implementation("org.springframework.security:spring-security-rsocket")
implementation("org.springframework.boot:spring-boot-starter-cache")
developmentOnly("org.springframework.boot:spring-boot-devtools")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.ehcache:ehcache:3.8.1")
implementation("javax.cache:cache-api:1.1.1")
implementation("org.flywaydb:flyway-core:7.10.0")
implementation("com.lmax:disruptor:3.4.2")
implementation("io.projectreactor.kotlin:reactor-kotlin-extensions")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
runtimeOnly("io.micrometer:micrometer-registry-prometheus")
runtimeOnly("io.r2dbc:r2dbc-postgresql")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("io.projectreactor:reactor-test")
testImplementation("org.springframework.security:spring-security-test")
}
configurations {
all {
exclude(group = "org.springframework.boot", module = "spring-boot-starter-logging")
exclude(group = "org.springframework.boot", module = "spring-boot-starter-tomcat")
exclude(group = "org.apache.tomcat.embed", module = "tomcat-embed-el")
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-jdk7")
}
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "1.8"
}
}
tasks.withType<Test> {
useJUnitPlatform()
}
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configguration>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout>
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%style{%t}{normal,red}] %highlight{%-5level } %style{%logger{36}}{bright,blue} %X - %msg %throwable%n</Pattern>
</PatternLayout>
</Console>
<Async name="AsyncConsole">
<AppenderRef ref="Console"/>
</Async>
</Appenders>
<Loggers>
<Logger name="some.package" level="DEBUG" additivity="false">
<AppenderRef ref="AsyncConsole"/>
</Logger>
<Root level="WARN" additivity="false">
<AppenderRef ref="AsyncConsole"/>
</Root>
</Loggers>
</Configguration>
Comment From: philwebb
Are you able to provide a sample application (either a zip file or a GitHub repo) that we can use to reproduce the problem?
Comment From: tormozzg
Hi. Here it is. demo.zip
This application has been created via initializer. There are only main class and custom log4j configuration.
Upd link to zip: build directory was removed to decrease archive size.
Comment From: wilkinsona
Thanks for the sample, @tormozzg. I've reproduced the problem.
We end up with a SimpleLoggerContext
as an attempt to get the "proper" LoggerContext
fails with an exception:
java.lang.IllegalStateException: Unable to register Log4j shutdown hook because JVM is shutting down.
at org.apache.logging.log4j.core.LoggerContext.setUpShutdownHook(LoggerContext.java:331)
at org.apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:274)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:245)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:47)
at org.apache.logging.log4j.LogManager.getContext(LogManager.java:176)
at org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.getLoggerContext(Log4J2LoggingSystem.java:329)
at org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.cleanUp(Log4J2LoggingSystem.java:310)
at org.springframework.boot.context.logging.LoggingApplicationListener.onContextClosedEvent(LoggingApplicationListener.java:258)
at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:223)
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.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:421)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:378)
at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1058)
at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.doClose(ReactiveWebServerApplicationContext.java:147)
at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:1021)
at org.springframework.boot.SpringApplicationShutdownHook.closeAndWait(SpringApplicationShutdownHook.java:128)
at java.lang.Iterable.forEach(Iterable.java:75)
at org.springframework.boot.SpringApplicationShutdownHook.run(SpringApplicationShutdownHook.java:100)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.IllegalStateException: Cannot add new shutdown hook as this is not started. Current state: STOPPED
at org.apache.logging.log4j.core.util.DefaultShutdownCallbackRegistry.addShutdownCallback(DefaultShutdownCallbackRegistry.java:138)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.addShutdownCallback(Log4jContextFactory.java:378)
at org.apache.logging.log4j.core.LoggerContext.setUpShutdownHook(LoggerContext.java:315)
... 20 more
java.lang.IllegalStateException: Unable to register Log4j shutdown hook because JVM is shutting down.
at org.apache.logging.log4j.core.LoggerContext.setUpShutdownHook(LoggerContext.java:331)
at org.apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:274)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:245)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:47)
at org.apache.logging.log4j.LogManager.getContext(LogManager.java:176)
at org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.getLoggerContext(Log4J2LoggingSystem.java:329)
at org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.cleanUp(Log4J2LoggingSystem.java:310)
at org.springframework.boot.context.logging.LoggingApplicationListener.onContextClosedEvent(LoggingApplicationListener.java:258)
at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:223)
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.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:421)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:378)
at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1058)
at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.doClose(ReactiveWebServerApplicationContext.java:147)
at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:1021)
at org.springframework.boot.SpringApplicationShutdownHook.closeAndWait(SpringApplicationShutdownHook.java:128)
at java.lang.Iterable.forEach(Iterable.java:75)
at org.springframework.boot.SpringApplicationShutdownHook.run(SpringApplicationShutdownHook.java:100)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.IllegalStateException: Cannot add new shutdown hook as this is not started. Current state: STOPPED
at org.apache.logging.log4j.core.util.DefaultShutdownCallbackRegistry.addShutdownCallback(DefaultShutdownCallbackRegistry.java:138)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.addShutdownCallback(Log4jContextFactory.java:378)
at org.apache.logging.log4j.core.LoggerContext.setUpShutdownHook(LoggerContext.java:315)
... 20 more
Log4j swallows this exception and returns a SimpleLoggerContext
.
Comment From: wilkinsona
@tormozzg You can avoid the problem by disabling Log4j's own shutdown hook (which it enables by default):
<Configuration shutdownHook="disable">
This will ensure that Log4j is shut down after the context has been closed so you won't lose any logging that happens during shutdown. We'll have to see what we can do to avoid the need for shutdownHook="disable"
in your custom <Configuration>
.
Comment From: tormozzg
Thanks. It helped.