From b85b60828c1d5d792e9771e888fa8e0cc85741af Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 20 Jan 2016 11:46:46 +0000 Subject: [PATCH] Perform background preinitialization after logging system setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, BackgroundPreinitializer would kick off preinitialization on a separate thread in response to an ApplicationStartedEvent. This work would then race with the logging system being set up in response to an ApplicationEnvironmentPreparedEvent. When Logback’s being used this race is problematic. As part of Logback’s setup, LoggerContext.stop() is called. This calls LoggerContext.reset() which can fail with a ConcurrentModificationException if another thread tries to create a Logger at the same time. This is a known bug in Logback [1]. This commit updates BackgroundPreinitializer to respond to an ApplicationEnvironmentPreparedEvent and to order itself so that it’s called after LoggingApplicationListener has responded to the same event by initializing the logging system. Closes gh-4871 [1] http://jira.qos.ch/browse/LOGBACK-397 --- .../boot/autoconfigure/BackgroundPreinitializer.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/BackgroundPreinitializer.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/BackgroundPreinitializer.java index 938aaf803f0..c44ac890b13 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/BackgroundPreinitializer.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/BackgroundPreinitializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,8 +23,10 @@ import javax.validation.Validation; import org.apache.catalina.mbeans.MBeanFactory; -import org.springframework.boot.context.event.ApplicationStartedEvent; +import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; +import org.springframework.boot.logging.LoggingApplicationListener; import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter; /** @@ -32,13 +34,15 @@ import org.springframework.http.converter.support.AllEncompassingFormHttpMessage * time consuming tasks. * * @author Phillip Webb + * @author Andy Wilkinson * @since 1.3.0 */ +@Order(LoggingApplicationListener.DEFAULT_ORDER + 1) public class BackgroundPreinitializer - implements ApplicationListener { + implements ApplicationListener { @Override - public void onApplicationEvent(ApplicationStartedEvent event) { + public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) { try { ExecutorService executor = Executors.newSingleThreadExecutor(); submit(executor, new MessageConverterInitializer());