Skip to content

Commit 00b668b

Browse files
committed
Only clean up logging system when root application context is closed
Previously, LoggingApplicationListener would clean up the logging system in response to any application context with which it was registered being closed. This caused problems when a child context was closed. Specifically, closing the child context would cause any SLF4J-based logging systems to unregister the JUL bridge handler preventing an JUL logging being bridged into Logback or Log4J2. This commit updates LoggingApplicationListener so that the logging system is only cleaned up when a root application context is closed. Closes gh-4651
1 parent d6bd120 commit 00b668b

File tree

2 files changed

+66
-1
lines changed

2 files changed

+66
-1
lines changed

spring-boot/src/main/java/org/springframework/boot/logging/LoggingApplicationListener.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ else if (event instanceof ApplicationEnvironmentPreparedEvent) {
145145
onApplicationEnvironmentPreparedEvent(
146146
(ApplicationEnvironmentPreparedEvent) event);
147147
}
148-
else if (event instanceof ContextClosedEvent) {
148+
else if (event instanceof ContextClosedEvent && ((ContextClosedEvent) event)
149+
.getApplicationContext().getParent() == null) {
149150
onContextClosedEvent();
150151
}
151152
}

spring-boot/src/test/java/org/springframework/boot/logging/LoggingApplicationListenerTests.java

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@
3939
import org.springframework.boot.test.OutputCapture;
4040
import org.springframework.context.event.ContextClosedEvent;
4141
import org.springframework.context.support.GenericApplicationContext;
42+
import org.springframework.test.util.ReflectionTestUtils;
4243

4344
import static org.hamcrest.Matchers.containsString;
45+
import static org.hamcrest.Matchers.is;
4446
import static org.hamcrest.Matchers.not;
4547
import static org.junit.Assert.assertFalse;
4648
import static org.junit.Assert.assertThat;
@@ -86,6 +88,7 @@ public void clear() {
8688
System.clearProperty("LOG_FILE");
8789
System.clearProperty("LOG_PATH");
8890
System.clearProperty("PID");
91+
System.clearProperty(LoggingSystem.SYSTEM_PROPERTY);
8992
if (this.context != null) {
9093
this.context.close();
9194
}
@@ -302,6 +305,37 @@ public void bridgeHandlerLifecycle() throws Exception {
302305
assertFalse(bridgeHandlerInstalled());
303306
}
304307

308+
@Test
309+
public void closingContextCleansUpLoggingSystem() {
310+
System.setProperty(LoggingSystem.SYSTEM_PROPERTY,
311+
TestCleanupLoggingSystem.class.getName());
312+
this.initializer.onApplicationEvent(
313+
new ApplicationStartedEvent(this.springApplication, new String[0]));
314+
TestCleanupLoggingSystem loggingSystem = (TestCleanupLoggingSystem) ReflectionTestUtils
315+
.getField(this.initializer, "loggingSystem");
316+
assertThat(loggingSystem.cleanedUp, is(false));
317+
this.initializer.onApplicationEvent(new ContextClosedEvent(this.context));
318+
assertThat(loggingSystem.cleanedUp, is(true));
319+
}
320+
321+
@Test
322+
public void closingChildContextDoesNotCleanUpLoggingSystem() {
323+
System.setProperty(LoggingSystem.SYSTEM_PROPERTY,
324+
TestCleanupLoggingSystem.class.getName());
325+
this.initializer.onApplicationEvent(
326+
new ApplicationStartedEvent(this.springApplication, new String[0]));
327+
TestCleanupLoggingSystem loggingSystem = (TestCleanupLoggingSystem) ReflectionTestUtils
328+
.getField(this.initializer, "loggingSystem");
329+
assertThat(loggingSystem.cleanedUp, is(false));
330+
GenericApplicationContext childContext = new GenericApplicationContext();
331+
childContext.setParent(this.context);
332+
this.initializer.onApplicationEvent(new ContextClosedEvent(childContext));
333+
assertThat(loggingSystem.cleanedUp, is(false));
334+
this.initializer.onApplicationEvent(new ContextClosedEvent(this.context));
335+
assertThat(loggingSystem.cleanedUp, is(true));
336+
childContext.close();
337+
}
338+
305339
private boolean bridgeHandlerInstalled() {
306340
Logger rootLogger = LogManager.getLogManager().getLogger("");
307341
Handler[] handlers = rootLogger.getHandlers();
@@ -312,4 +346,34 @@ private boolean bridgeHandlerInstalled() {
312346
}
313347
return false;
314348
}
349+
350+
static final class TestCleanupLoggingSystem extends LoggingSystem {
351+
352+
private boolean cleanedUp = false;
353+
354+
public TestCleanupLoggingSystem(ClassLoader classLoader) {
355+
356+
}
357+
358+
@Override
359+
public void beforeInitialize() {
360+
361+
}
362+
363+
@Override
364+
public void initialize(String configLocation, LogFile logFile) {
365+
366+
}
367+
368+
@Override
369+
public void setLogLevel(String loggerName, LogLevel level) {
370+
371+
}
372+
373+
@Override
374+
public void cleanUp() {
375+
this.cleanedUp = true;
376+
}
377+
378+
}
315379
}

0 commit comments

Comments
 (0)