From 57ebdab2ab624b3dad7349153ce84374e235c0df Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 11 Jul 2018 11:47:17 +0100 Subject: [PATCH] Delay property source initialization till LoggingSystem is initialized Previously, the initialization of StandardServletEnvironment's property sources in SpringBootServletInitializer led to debug logging calls being made before the LoggingSystem had been initialized. As a result, the system's default configuration was used and, in the case of Logback at least, the debug logging was output to System.out in a war deployment. This commit updates SpringBootServletInitializer to delay the initialization of StandardServletEnvironment's property sources until after the LoggingSystem has been initialized, but still in time for active profiles to be configured via servlet context parameters (see gh-9972). Closes gh-13736 --- .../support/SpringBootServletInitializer.java | 36 ++++++++++++++++--- .../SpringBootServletInitializerTests.java | 13 ++++++- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/spring-boot/src/main/java/org/springframework/boot/web/support/SpringBootServletInitializer.java b/spring-boot/src/main/java/org/springframework/boot/web/support/SpringBootServletInitializer.java index 1e1d809702c..f4c2287d89d 100644 --- a/spring-boot/src/main/java/org/springframework/boot/web/support/SpringBootServletInitializer.java +++ b/spring-boot/src/main/java/org/springframework/boot/web/support/SpringBootServletInitializer.java @@ -29,15 +29,19 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.builder.ParentContextApplicationContextInitializer; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext; +import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.Configuration; +import org.springframework.core.Ordered; import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.util.Assert; import org.springframework.web.WebApplicationInitializer; +import org.springframework.web.context.ConfigurableWebEnvironment; import org.springframework.web.context.ContextLoaderListener; import org.springframework.web.context.WebApplicationContext; -import org.springframework.web.context.support.StandardServletEnvironment; /** * An opinionated {@link WebApplicationInitializer} to run a {@link SpringApplication} @@ -104,9 +108,6 @@ public abstract class SpringBootServletInitializer implements WebApplicationInit protected WebApplicationContext createRootApplicationContext( ServletContext servletContext) { SpringApplicationBuilder builder = createSpringApplicationBuilder(); - StandardServletEnvironment environment = new StandardServletEnvironment(); - environment.initPropertySources(servletContext, null); - builder.environment(environment); builder.main(getClass()); ApplicationContext parent = getExistingRootWebApplicationContext(servletContext); if (parent != null) { @@ -119,6 +120,7 @@ public abstract class SpringBootServletInitializer implements WebApplicationInit new ServletContextApplicationContextInitializer(servletContext)); builder.contextClass(AnnotationConfigEmbeddedWebApplicationContext.class); builder = configure(builder); + builder.listeners(new WebEnvironmentPropertySourceInitializer(servletContext)); SpringApplication application = builder.build(); if (application.getSources().isEmpty() && AnnotationUtils .findAnnotation(getClass(), Configuration.class) != null) { @@ -177,4 +179,30 @@ public abstract class SpringBootServletInitializer implements WebApplicationInit return builder; } + private static final class WebEnvironmentPropertySourceInitializer + implements ApplicationListener, Ordered { + + private final ServletContext servletContext; + + private WebEnvironmentPropertySourceInitializer(ServletContext servletContext) { + this.servletContext = servletContext; + } + + @Override + public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) { + ConfigurableEnvironment environment = event.getEnvironment(); + if (environment instanceof ConfigurableWebEnvironment) { + ((ConfigurableWebEnvironment) environment) + .initPropertySources(this.servletContext, null); + } + + } + + @Override + public int getOrder() { + return Ordered.HIGHEST_PRECEDENCE; + } + + } + } diff --git a/spring-boot/src/test/java/org/springframework/boot/web/support/SpringBootServletInitializerTests.java b/spring-boot/src/test/java/org/springframework/boot/web/support/SpringBootServletInitializerTests.java index b0afd27835d..9b01292141e 100644 --- a/spring-boot/src/test/java/org/springframework/boot/web/support/SpringBootServletInitializerTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/web/support/SpringBootServletInitializerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2018 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. @@ -22,6 +22,7 @@ import java.util.Collections; import javax.servlet.ServletContext; import javax.servlet.ServletException; +import org.junit.After; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -33,6 +34,7 @@ import org.springframework.boot.context.embedded.EmbeddedServletContainer; import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory; import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; +import org.springframework.boot.testutil.InternalOutputCapture; import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.context.ApplicationListener; import org.springframework.context.ConfigurableApplicationContext; @@ -59,10 +61,19 @@ public class SpringBootServletInitializerTests { @Rule public ExpectedException thrown = ExpectedException.none(); + @Rule + public InternalOutputCapture output = new InternalOutputCapture(); + private ServletContext servletContext = new MockServletContext(); private SpringApplication application; + @After + public void verifyLoggingOutput() { + assertThat(this.output.toString()) + .doesNotContain(StandardServletEnvironment.class.getSimpleName()); + } + @Test public void failsWithoutConfigure() throws Exception { this.thrown.expect(IllegalStateException.class);