From 1070e4d5c1daec820f12ea39a4d665106d1e9539 Mon Sep 17 00:00:00 2001 From: Chris Beams Date: Fri, 2 Nov 2012 12:56:14 +0100 Subject: [PATCH] Initialize FrameworkServlet property sources eagerly Prior to this change, FrameworkServlet#configureAndRefreshWebApplicationContext called #postProcessWebApplicationContext(wac) and #applyInitializers(wac) prior to #refresh, but because servlet-based property source stubs were not replaced until #refresh, any post-processing or initialization routines could not benefit from accessing the Environment to retrieve properties from the ServletContext or ServletConfig. The workaround to this problem is detailed in SPR-9610 - the user simply needed to call WebApplicationContextUtils#initServletPropertySources manually within their ApplicationContextInitializer (or overridden #postProcessWebApplicationContext method) This commit ensures that FrameworkServlet#configureAndRefreshWebApplicationContext calls WebApplicationContextUtils#initServletPropertySources eagerly, prior to invoking #postProcessWebApplicationContext and #applyInitializers. Related Javadoc has also been updated throughout to clarify the behavior of #initServletPropertySources, when it can be called and what the effects are, etc. Note also that a reproduction issue was added to demonstrate the problem and verify its resolution [1]. [1]: https://github.com/SpringSource/spring-framework-issues/tree/master/SPR-9610 Issue: SPR-9610 --- .../context/ConfigurableWebEnvironment.java | 2 ++ .../support/WebApplicationContextUtils.java | 27 ++++++++++++------- .../PortletApplicationContextUtils.java | 22 ++++++++++++--- .../web/servlet/FrameworkServlet.java | 6 +++++ 4 files changed, 44 insertions(+), 13 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/web/context/ConfigurableWebEnvironment.java b/spring-web/src/main/java/org/springframework/web/context/ConfigurableWebEnvironment.java index 8d5758cfcd..241f102319 100644 --- a/spring-web/src/main/java/org/springframework/web/context/ConfigurableWebEnvironment.java +++ b/spring-web/src/main/java/org/springframework/web/context/ConfigurableWebEnvironment.java @@ -40,6 +40,8 @@ public interface ConfigurableWebEnvironment extends ConfigurableEnvironment { * using the given parameters. * @param servletContext the {@link ServletContext} (may not be {@code null}) * @param servletConfig the {@link ServletConfig} ({@code null} if not available) + * @see org.springframework.web.context.support.WebApplicationContextUtils#initServletPropertySources( + * org.springframework.core.env.MutablePropertySources, ServletContext, ServletConfig) */ void initPropertySources(ServletContext servletContext, ServletConfig servletConfig); diff --git a/spring-web/src/main/java/org/springframework/web/context/support/WebApplicationContextUtils.java b/spring-web/src/main/java/org/springframework/web/context/support/WebApplicationContextUtils.java index 9b9426d112..8785dbb2f3 100644 --- a/spring-web/src/main/java/org/springframework/web/context/support/WebApplicationContextUtils.java +++ b/spring-web/src/main/java/org/springframework/web/context/support/WebApplicationContextUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2012 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. @@ -230,11 +230,10 @@ public abstract class WebApplicationContextUtils { } /** - * Replace {@code Servlet}-based stub property sources with actual instances - * populated with the given context object. - * @see org.springframework.core.env.PropertySource.StubPropertySource - * @see org.springframework.core.env.ConfigurableEnvironment#getPropertySources() - * @see org.springframework.web.context.support.WebApplicationContextUtils#initServletPropertySources(MutablePropertySources, ServletContext) + * Convenient variant of {@link #initServletPropertySources(MutablePropertySources, + * ServletContext, ServletConfig)} that always provides {@code null} for the + * {@link ServletConfig} parameter. + * @see #initServletPropertySources(MutablePropertySources, ServletContext, ServletConfig) */ public static void initServletPropertySources( MutablePropertySources propertySources, ServletContext servletContext) { @@ -242,10 +241,20 @@ public abstract class WebApplicationContextUtils { } /** - * Replace {@code Servlet}-based stub property sources with actual instances - * populated with the given context and config objects. + * Replace {@code Servlet}-based {@link StubPropertySource stub property sources} with + * actual instances populated with the given {@code servletContext} and + * {@code servletConfig} objects. + *

This method is idempotent with respect to the fact it may be called any number + * of times but will perform replacement of stub property sources with their + * corresponding actual property sources once and only once. + * @param propertySources the {@link PropertySources} to initialize (must not be {@code null}) + * @param servletContext the current {@link ServletContext} (ignored if {@code null} + * or if the {@link StandardServletEnvironment#SERVLET_CONTEXT_PROPERTY_SOURCE_NAME + * servlet context property source} has already been initialized) + * @param servletConfig the current {@link ServletConfig} (ignored if {@code null} + * or if the {@link StandardServletEnvironment#SERVLET_CONFIG_PROPERTY_SOURCE_NAME + * servlet config property source} has already been initialized) * @see org.springframework.core.env.PropertySource.StubPropertySource - * @see org.springframework.web.context.support.WebApplicationContextUtils#initServletPropertySources(MutablePropertySources, ServletContext) * @see org.springframework.core.env.ConfigurableEnvironment#getPropertySources() */ public static void initServletPropertySources( diff --git a/spring-webmvc-portlet/src/main/java/org/springframework/web/portlet/context/PortletApplicationContextUtils.java b/spring-webmvc-portlet/src/main/java/org/springframework/web/portlet/context/PortletApplicationContextUtils.java index ef1bebd211..b486de6492 100644 --- a/spring-webmvc-portlet/src/main/java/org/springframework/web/portlet/context/PortletApplicationContextUtils.java +++ b/spring-webmvc-portlet/src/main/java/org/springframework/web/portlet/context/PortletApplicationContextUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2012 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. @@ -188,11 +188,25 @@ public abstract class PortletApplicationContextUtils { } /** - * Replace {@code Servlet}- and {@code Portlet}-based stub property sources - * with actual instances populated with the given context and config objects. + * Replace {@code Servlet}- and {@code Portlet}-based {@link StubPropertySource stub + * property sources} with actual instances populated with the given {@code servletContext}, + * {@code portletContext} and {@code portletConfig} objects. + *

This method is idempotent with respect to the fact it may be called any number + * of times but will perform replacement of stub property sources with their + * corresponding actual property sources once and only once. + * @param propertySources the {@link PropertySources} to initialize (must not be {@code null}) + * @param servletContext the current {@link ServletContext} (ignored if {@code null} + * or if the {@link StandardServletEnvironment#SERVLET_CONTEXT_PROPERTY_SOURCE_NAME + * servlet context property source} has already been initialized) + * @param portletContext the current {@link PortletContext} (ignored if {@code null} + * or if the {@link StandardPortletEnvironment#PORTLET_CONTEXT_PROPERTY_SOURCE_NAME + * portlet context property source} has already been initialized) + * @param portletConfig the current {@link PortletConfig} (ignored if {@code null} + * or if the {@link StandardPortletEnvironment#PORTLET_CONFIG_PROPERTY_SOURCE_NAME + * portlet config property source} has already been initialized) * @see org.springframework.core.env.PropertySource.StubPropertySource - * @see org.springframework.core.env.ConfigurableEnvironment#getPropertySources() * @see org.springframework.web.context.support.WebApplicationContextUtils#initServletPropertySources(MutablePropertySources, ServletContext) + * @see org.springframework.core.env.ConfigurableEnvironment#getPropertySources() */ public static void initPortletPropertySources(MutablePropertySources propertySources, ServletContext servletContext, PortletContext portletContext, PortletConfig portletConfig) { diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/FrameworkServlet.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/FrameworkServlet.java index a3b2f461eb..5005efb8eb 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/FrameworkServlet.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/FrameworkServlet.java @@ -634,6 +634,12 @@ public abstract class FrameworkServlet extends HttpServletBean { wac.setNamespace(getNamespace()); wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener())); + // the wac environment's #initPropertySources will be called in any case when + // the context is refreshed; do it eagerly here to ensure servlet property sources + // are in place for use in any post-processing or initialization that occurs + // below prior to #refresh + wac.getEnvironment().initPropertySources(getServletContext(), getServletConfig()); + postProcessWebApplicationContext(wac); applyInitializers(wac);