diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/context/ContextLoaderTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/context/ContextLoaderTests.java index a515820f359..836e17a5ff5 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/context/ContextLoaderTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/context/ContextLoaderTests.java @@ -17,6 +17,7 @@ package org.springframework.web.context; import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -131,6 +132,19 @@ public final class ContextLoaderTests { assertThat(wac.getServletContext().getAttribute("initialized"), notNullValue()); } + @Test + public void testRegisteredContextInitializerCanAccessServletContextParamsViaEnvironment() { + MockServletContext sc = new MockServletContext(""); + // config file doesn't matter. just a placeholder + sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM, + "/org/springframework/web/context/WEB-INF/empty-context.xml"); + + sc.addInitParameter("someProperty", "someValue"); + sc.addInitParameter(ContextLoader.CONTEXT_INITIALIZER_CLASSES_PARAM, EnvApplicationContextInitializer.class.getName()); + ContextLoaderListener listener = new ContextLoaderListener(); + listener.contextInitialized(new ServletContextEvent(sc)); + } + @Test public void testContextLoaderListenerWithUnkownContextInitializer() { MockServletContext sc = new MockServletContext(""); @@ -324,6 +338,15 @@ public final class ContextLoaderTests { } } + private static class EnvApplicationContextInitializer implements ApplicationContextInitializer { + public void initialize(ConfigurableWebApplicationContext applicationContext) { + // test that ApplicationContextInitializers can access ServletContext properties + // via the environment (SPR-8991) + String value = applicationContext.getEnvironment().getRequiredProperty("someProperty"); + assertThat(value, is("someValue")); + } + } + private static interface UnknownApplicationContext extends ConfigurableApplicationContext { void unheardOf(); } diff --git a/org.springframework.web/src/main/java/org/springframework/web/context/ContextLoader.java b/org.springframework.web/src/main/java/org/springframework/web/context/ContextLoader.java index 25c8fa14cb9..79c3d8744ca 100644 --- a/org.springframework.web/src/main/java/org/springframework/web/context/ContextLoader.java +++ b/org.springframework.web/src/main/java/org/springframework/web/context/ContextLoader.java @@ -44,6 +44,7 @@ import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; +import org.springframework.web.context.support.WebApplicationContextUtils; /** * Performs the actual initialization work for the root application context. @@ -487,6 +488,13 @@ public class ContextLoader { Collections.sort(initializerInstances, new AnnotationAwareOrderComparator()); + // eagerly attempt to initialize servlet property sources in case initializers + // below depend on accessing context-params via the Environment API. Note that + // depending on application context implementation, this initialization will be + // attempted again during context refresh. + WebApplicationContextUtils.initServletPropertySources( + applicationContext.getEnvironment().getPropertySources(), servletContext); + for (ApplicationContextInitializer initializer : initializerInstances) { initializer.initialize(applicationContext); } diff --git a/org.springframework.web/src/main/java/org/springframework/web/context/support/WebApplicationContextUtils.java b/org.springframework.web/src/main/java/org/springframework/web/context/support/WebApplicationContextUtils.java index eb607d1c318..9b9426d112f 100644 --- a/org.springframework.web/src/main/java/org/springframework/web/context/support/WebApplicationContextUtils.java +++ b/org.springframework.web/src/main/java/org/springframework/web/context/support/WebApplicationContextUtils.java @@ -16,6 +16,9 @@ package org.springframework.web.context.support; +import static org.springframework.web.context.support.StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME; +import static org.springframework.web.context.support.StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME; + import java.io.Serializable; import java.util.Collections; import java.util.Enumeration; @@ -32,6 +35,7 @@ import javax.servlet.http.HttpSession; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.core.env.MutablePropertySources; +import org.springframework.core.env.PropertySource.StubPropertySource; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.web.context.ConfigurableWebApplicationContext; @@ -247,13 +251,15 @@ public abstract class WebApplicationContextUtils { public static void initServletPropertySources( MutablePropertySources propertySources, ServletContext servletContext, ServletConfig servletConfig) { Assert.notNull(propertySources, "propertySources must not be null"); - if(servletContext != null && propertySources.contains(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME)) { - propertySources.replace(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME, - new ServletContextPropertySource(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME, servletContext)); + if(servletContext != null && + propertySources.contains(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME) && + propertySources.get(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME) instanceof StubPropertySource) { + propertySources.replace(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME, new ServletContextPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME, servletContext)); } - if(servletConfig != null && propertySources.contains(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME)) { - propertySources.replace(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME, - new ServletConfigPropertySource(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME, servletConfig)); + if(servletConfig != null && + propertySources.contains(SERVLET_CONFIG_PROPERTY_SOURCE_NAME) && + propertySources.get(SERVLET_CONFIG_PROPERTY_SOURCE_NAME) instanceof StubPropertySource) { + propertySources.replace(SERVLET_CONFIG_PROPERTY_SOURCE_NAME, new ServletConfigPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME, servletConfig)); } }