Perform background preinitialization after logging system setup

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
pull/4984/head
Andy Wilkinson 9 years ago
parent 00f4538529
commit b85b60828c

@ -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<ApplicationStartedEvent> {
implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
try {
ExecutorService executor = Executors.newSingleThreadExecutor();
submit(executor, new MessageConverterInitializer());

Loading…
Cancel
Save