diff --git a/spring-web/src/main/java/org/springframework/web/context/ContextLoader.java b/spring-web/src/main/java/org/springframework/web/context/ContextLoader.java
index 9f45686fefd..16da9161d32 100644
--- a/spring-web/src/main/java/org/springframework/web/context/ContextLoader.java
+++ b/spring-web/src/main/java/org/springframework/web/context/ContextLoader.java
@@ -77,8 +77,8 @@ import org.springframework.util.StringUtils;
*
*
As of Spring 3.1, {@code ContextLoader} supports injecting the root web
* application context via the {@link #ContextLoader(WebApplicationContext)}
- * constructor, allowing for programmatic configuration in Servlet 3.0+ environments. See
- * {@link org.springframework.web.WebApplicationInitializer} for usage examples.
+ * constructor, allowing for programmatic configuration in Servlet 3.0+ environments.
+ * See {@link org.springframework.web.WebApplicationInitializer} for usage examples.
*
* @author Juergen Hoeller
* @author Colin Sampaleanu
@@ -90,6 +90,20 @@ import org.springframework.util.StringUtils;
*/
public class ContextLoader {
+ /**
+ * Config param for the root WebApplicationContext id,
+ * to be used as serialization id for the underlying BeanFactory: {@value}
+ */
+ public static final String CONTEXT_ID_PARAM = "contextId";
+
+ /**
+ * Name of servlet context parameter (i.e., {@value}) that can specify the
+ * config location for the root context, falling back to the implementation's
+ * default otherwise.
+ * @see org.springframework.web.context.support.XmlWebApplicationContext#DEFAULT_CONFIG_LOCATION
+ */
+ public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation";
+
/**
* Config param for the root WebApplicationContext implementation class to use: {@value}
* @see #determineContextClass(ServletContext)
@@ -98,25 +112,18 @@ public class ContextLoader {
public static final String CONTEXT_CLASS_PARAM = "contextClass";
/**
- * Config param for the root WebApplicationContext id,
- * to be used as serialization id for the underlying BeanFactory: {@value}
- */
- public static final String CONTEXT_ID_PARAM = "contextId";
-
- /**
- * Config param for which {@link ApplicationContextInitializer} classes to use
- * for initializing the web application context: {@value}
+ * Config param for {@link ApplicationContextInitializer} classes to use
+ * for initializing the root web application context: {@value}
* @see #customizeContext(ServletContext, ConfigurableWebApplicationContext)
*/
public static final String CONTEXT_INITIALIZER_CLASSES_PARAM = "contextInitializerClasses";
/**
- * Name of servlet context parameter (i.e., {@value}) that can specify the
- * config location for the root context, falling back to the implementation's
- * default otherwise.
- * @see org.springframework.web.context.support.XmlWebApplicationContext#DEFAULT_CONFIG_LOCATION
+ * Config param for global {@link ApplicationContextInitializer} classes to use
+ * for initializing all web application contexts in the current application: {@value}
+ * @see #customizeContext(ServletContext, ConfigurableWebApplicationContext)
*/
- public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation";
+ public static final String GLOBAL_INITIALIZER_CLASSES_PARAM = "globalInitializerClasses";
/**
* Optional servlet context parameter (i.e., "{@code locatorFactorySelector}")
@@ -146,6 +153,12 @@ public class ContextLoader {
*/
public static final String LOCATOR_FACTORY_KEY_PARAM = "parentContextKey";
+ /**
+ * Any number of these characters are considered delimiters between
+ * multiple values in a single init-param String value.
+ */
+ private static final String INIT_PARAM_DELIMITERS = ",; \t\n";
+
/**
* Name of the class path resource (relative to the ContextLoader class)
* that defines ContextLoader's default strategy names.
@@ -373,14 +386,71 @@ public class ContextLoader {
}
wac.setServletContext(sc);
- String initParameter = sc.getInitParameter(CONFIG_LOCATION_PARAM);
- if (initParameter != null) {
- wac.setConfigLocation(initParameter);
+ String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
+ if (configLocationParam != null) {
+ wac.setConfigLocation(configLocationParam);
}
+
+ // 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
+ ConfigurableEnvironment env = wac.getEnvironment();
+ if (env instanceof ConfigurableWebEnvironment) {
+ ((ConfigurableWebEnvironment) env).initPropertySources(sc, null);
+ }
+
customizeContext(sc, wac);
wac.refresh();
}
+ /**
+ * Customize the {@link ConfigurableWebApplicationContext} created by this
+ * ContextLoader after config locations have been supplied to the context
+ * but before the context is refreshed.
+ *
The default implementation {@linkplain #determineContextInitializerClasses(ServletContext)
+ * determines} what (if any) context initializer classes have been specified through
+ * {@linkplain #CONTEXT_INITIALIZER_CLASSES_PARAM context init parameters} and
+ * {@linkplain ApplicationContextInitializer#initialize invokes each} with the
+ * given web application context.
+ *
Any {@code ApplicationContextInitializers} implementing
+ * {@link org.springframework.core.Ordered Ordered} or marked with @{@link
+ * org.springframework.core.annotation.Order Order} will be sorted appropriately.
+ * @param sc the current servlet context
+ * @param wac the newly created application context
+ * @see #createWebApplicationContext(ServletContext, ApplicationContext)
+ * @see #CONTEXT_INITIALIZER_CLASSES_PARAM
+ * @see ApplicationContextInitializer#initialize(ConfigurableApplicationContext)
+ */
+ protected void customizeContext(ServletContext sc, ConfigurableWebApplicationContext wac) {
+ List>> initializerClasses =
+ determineContextInitializerClasses(sc);
+ if (initializerClasses.isEmpty()) {
+ // no ApplicationContextInitializers have been declared -> nothing to do
+ return;
+ }
+
+ ArrayList> initializerInstances =
+ new ArrayList>();
+
+ for (Class> initializerClass : initializerClasses) {
+ Class> initializerContextClass =
+ GenericTypeResolver.resolveTypeArgument(initializerClass, ApplicationContextInitializer.class);
+ if (initializerContextClass != null) {
+ Assert.isAssignable(initializerContextClass, wac.getClass(), String.format(
+ "Could not add context initializer [%s] since its generic parameter [%s] " +
+ "is not assignable from the type of application context used by this " +
+ "context loader [%s]: ", initializerClass.getName(), initializerContextClass.getName(),
+ wac.getClass().getName()));
+ }
+ initializerInstances.add(BeanUtils.instantiateClass(initializerClass));
+ }
+
+ AnnotationAwareOrderComparator.sort(initializerInstances);
+ for (ApplicationContextInitializer initializer : initializerInstances) {
+ initializer.initialize(wac);
+ }
+ }
+
/**
* Return the WebApplicationContext implementation class to use, either the
* default XmlWebApplicationContext or a custom context class if specified.
@@ -418,80 +488,38 @@ public class ContextLoader {
* @param servletContext current servlet context
* @see #CONTEXT_INITIALIZER_CLASSES_PARAM
*/
- @SuppressWarnings("unchecked")
protected List>>
determineContextInitializerClasses(ServletContext servletContext) {
- String classNames = servletContext.getInitParameter(CONTEXT_INITIALIZER_CLASSES_PARAM);
+
List>> classes =
- new ArrayList>>();
- if (classNames != null) {
- for (String className : StringUtils.tokenizeToStringArray(classNames, ",")) {
- try {
- Class> clazz = ClassUtils.forName(className, ClassUtils.getDefaultClassLoader());
- Assert.isAssignable(ApplicationContextInitializer.class, clazz,
- "class [" + className + "] must implement ApplicationContextInitializer");
- classes.add((Class>)clazz);
- }
- catch (ClassNotFoundException ex) {
- throw new ApplicationContextException(
- "Failed to load context initializer class [" + className + "]", ex);
- }
- }
- }
- return classes;
- }
+ new ArrayList>>();
- /**
- * Customize the {@link ConfigurableWebApplicationContext} created by this
- * ContextLoader after config locations have been supplied to the context
- * but before the context is refreshed.
- * The default implementation {@linkplain #determineContextInitializerClasses(ServletContext)
- * determines} what (if any) context initializer classes have been specified through
- * {@linkplain #CONTEXT_INITIALIZER_CLASSES_PARAM context init parameters} and
- * {@linkplain ApplicationContextInitializer#initialize invokes each} with the
- * given web application context.
- *
Any {@code ApplicationContextInitializers} implementing
- * {@link org.springframework.core.Ordered Ordered} or marked with @{@link
- * org.springframework.core.annotation.Order Order} will be sorted appropriately.
- * @param servletContext the current servlet context
- * @param applicationContext the newly created application context
- * @see #createWebApplicationContext(ServletContext, ApplicationContext)
- * @see #CONTEXT_INITIALIZER_CLASSES_PARAM
- * @see ApplicationContextInitializer#initialize(ConfigurableApplicationContext)
- */
- protected void customizeContext(ServletContext servletContext, ConfigurableWebApplicationContext applicationContext) {
- List>> initializerClasses =
- determineContextInitializerClasses(servletContext);
- if (initializerClasses.isEmpty()) {
- // no ApplicationContextInitializers have been declared -> nothing to do
- return;
+ String globalClassNames = servletContext.getInitParameter(GLOBAL_INITIALIZER_CLASSES_PARAM);
+ if (globalClassNames != null) {
+ for (String className : StringUtils.tokenizeToStringArray(globalClassNames, INIT_PARAM_DELIMITERS)) {
+ classes.add(loadInitializerClass(className));
+ }
}
- Class> contextClass = applicationContext.getClass();
- ArrayList> initializerInstances =
- new ArrayList>();
-
- for (Class> initializerClass : initializerClasses) {
- Class> initializerContextClass =
- GenericTypeResolver.resolveTypeArgument(initializerClass, ApplicationContextInitializer.class);
- if (initializerContextClass != null) {
- Assert.isAssignable(initializerContextClass, contextClass, String.format(
- "Could not add context initializer [%s] as its generic parameter [%s] " +
- "is not assignable from the type of application context used by this " +
- "context loader [%s]: ", initializerClass.getName(), initializerContextClass.getName(),
- contextClass.getName()));
+ String localClassNames = servletContext.getInitParameter(CONTEXT_INITIALIZER_CLASSES_PARAM);
+ if (localClassNames != null) {
+ for (String className : StringUtils.tokenizeToStringArray(localClassNames, INIT_PARAM_DELIMITERS)) {
+ classes.add(loadInitializerClass(className));
}
- initializerInstances.add(BeanUtils.instantiateClass(initializerClass));
}
- ConfigurableEnvironment env = applicationContext.getEnvironment();
- if (env instanceof ConfigurableWebEnvironment) {
- ((ConfigurableWebEnvironment) env).initPropertySources(servletContext, null);
- }
+ return classes;
+ }
- AnnotationAwareOrderComparator.sort(initializerInstances);
- for (ApplicationContextInitializer initializer : initializerInstances) {
- initializer.initialize(applicationContext);
+ @SuppressWarnings("unchecked")
+ private Class> loadInitializerClass(String className) {
+ try {
+ Class> clazz = ClassUtils.forName(className, ClassUtils.getDefaultClassLoader());
+ Assert.isAssignable(ApplicationContextInitializer.class, clazz);
+ return (Class>) clazz;
+ }
+ catch (ClassNotFoundException ex) {
+ throw new ApplicationContextException("Failed to load context initializer class [" + className + "]", ex);
}
}
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 6dde6d8dc1d..6b2ffa4f079 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
@@ -20,7 +20,6 @@ import java.io.IOException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.concurrent.Callable;
-
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@@ -40,14 +39,17 @@ import org.springframework.context.event.SourceFilteringListener;
import org.springframework.context.i18n.LocaleContext;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.i18n.SimpleLocaleContext;
+import org.springframework.core.GenericTypeResolver;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.ConfigurableWebApplicationContext;
import org.springframework.web.context.ConfigurableWebEnvironment;
+import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
@@ -175,6 +177,13 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
/** Explicit context config location */
private String contextConfigLocation;
+ /** Actual ApplicationContextInitializer instances to apply to the context */
+ private final ArrayList> contextInitializers =
+ new ArrayList>();
+
+ /** Comma-delimited ApplicationContextInitializer class names set through init param */
+ private String contextInitializerClasses;
+
/** Should we publish the context as a ServletContext attribute? */
private boolean publishContext = true;
@@ -199,13 +208,6 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
/** Flag used to detect whether onRefresh has already been called */
private boolean refreshEventReceived = false;
- /** Comma-delimited ApplicationContextInitializer classnames set through init param */
- private String contextInitializerClasses;
-
- /** Actual ApplicationContextInitializer instances to apply to the context */
- private ArrayList> contextInitializers =
- new ArrayList>();
-
/**
* Create a new {@code FrameworkServlet} that will create its own internal web
@@ -340,13 +342,19 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
}
/**
- * Specify the set of fully-qualified {@link ApplicationContextInitializer} class
- * names, per the optional "contextInitializerClasses" servlet init-param.
- * @see #configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext)
- * @see #applyInitializers(ConfigurableApplicationContext)
+ * Set the context config location explicitly, instead of relying on the default
+ * location built from the namespace. This location string can consist of
+ * multiple locations separated by any number of commas and spaces.
*/
- public void setContextInitializerClasses(String contextInitializerClasses) {
- this.contextInitializerClasses = contextInitializerClasses;
+ public void setContextConfigLocation(String contextConfigLocation) {
+ this.contextConfigLocation = contextConfigLocation;
+ }
+
+ /**
+ * Return the explicit context config location, if any.
+ */
+ public String getContextConfigLocation() {
+ return this.contextConfigLocation;
}
/**
@@ -355,7 +363,6 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
* @see #configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext)
* @see #applyInitializers(ConfigurableApplicationContext)
*/
- @SuppressWarnings("unchecked")
public void setContextInitializers(ApplicationContextInitializer... contextInitializers) {
for (ApplicationContextInitializer initializer : contextInitializers) {
this.contextInitializers.add(initializer);
@@ -363,19 +370,13 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
}
/**
- * Set the context config location explicitly, instead of relying on the default
- * location built from the namespace. This location string can consist of
- * multiple locations separated by any number of commas and spaces.
- */
- public void setContextConfigLocation(String contextConfigLocation) {
- this.contextConfigLocation = contextConfigLocation;
- }
-
- /**
- * Return the explicit context config location, if any.
+ * Specify the set of fully-qualified {@link ApplicationContextInitializer} class
+ * names, per the optional "contextInitializerClasses" servlet init-param.
+ * @see #configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext)
+ * @see #applyInitializers(ConfigurableApplicationContext)
*/
- public String getContextConfigLocation() {
- return this.contextConfigLocation;
+ public void setContextInitializerClasses(String contextInitializerClasses) {
+ this.contextInitializerClasses = contextInitializerClasses;
}
/**
@@ -627,19 +628,16 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
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
+ // 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
ConfigurableEnvironment env = wac.getEnvironment();
if (env instanceof ConfigurableWebEnvironment) {
- ((ConfigurableWebEnvironment)env).initPropertySources(getServletContext(), getServletConfig());
+ ((ConfigurableWebEnvironment) env).initPropertySources(getServletContext(), getServletConfig());
}
postProcessWebApplicationContext(wac);
-
applyInitializers(wac);
-
wac.refresh();
}
@@ -657,58 +655,75 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
return createWebApplicationContext((ApplicationContext) parent);
}
+ /**
+ * Post-process the given WebApplicationContext before it is refreshed
+ * and activated as context for this servlet.
+ * The default implementation is empty. {@code refresh()} will
+ * be called automatically after this method returns.
+ *
Note that this method is designed to allow subclasses to modify the application
+ * context, while {@link #initWebApplicationContext} is designed to allow
+ * end-users to modify the context through the use of
+ * {@link ApplicationContextInitializer}s.
+ * @param wac the configured WebApplicationContext (not refreshed yet)
+ * @see #createWebApplicationContext
+ * @see #initWebApplicationContext
+ * @see ConfigurableWebApplicationContext#refresh()
+ */
+ protected void postProcessWebApplicationContext(ConfigurableWebApplicationContext wac) {
+ }
+
/**
* Delegate the WebApplicationContext before it is refreshed to any
* {@link ApplicationContextInitializer} instances specified by the
* "contextInitializerClasses" servlet init-param.
*
See also {@link #postProcessWebApplicationContext}, which is designed to allow
* subclasses (as opposed to end-users) to modify the application context, and is
- * called immediately after this method.
+ * called immediately before this method.
* @param wac the configured WebApplicationContext (not refreshed yet)
* @see #createWebApplicationContext
* @see #postProcessWebApplicationContext
* @see ConfigurableApplicationContext#refresh()
*/
- @SuppressWarnings("unchecked")
protected void applyInitializers(ConfigurableApplicationContext wac) {
+ String globalClassNames = getServletContext().getInitParameter(ContextLoader.GLOBAL_INITIALIZER_CLASSES_PARAM);
+ if (globalClassNames != null) {
+ for (String className : StringUtils.tokenizeToStringArray(globalClassNames, INIT_PARAM_DELIMITERS)) {
+ this.contextInitializers.add(loadInitializer(className, wac));
+ }
+ }
+
if (this.contextInitializerClasses != null) {
- String[] initializerClassNames =
- StringUtils.tokenizeToStringArray(this.contextInitializerClasses, INIT_PARAM_DELIMITERS);
- for (String initializerClassName : initializerClassNames) {
- ApplicationContextInitializer initializer;
- try {
- Class> initializerClass = ClassUtils.forName(initializerClassName, wac.getClassLoader());
- initializer = BeanUtils.instantiateClass(initializerClass, ApplicationContextInitializer.class);
- }
- catch (Exception ex) {
- throw new IllegalArgumentException(
- String.format("Could not instantiate class [%s] specified via " +
- "'contextInitializerClasses' init-param", initializerClassName), ex);
- }
- this.contextInitializers.add(initializer);
+ for (String className : StringUtils.tokenizeToStringArray(this.contextInitializerClasses, INIT_PARAM_DELIMITERS)) {
+ this.contextInitializers.add(loadInitializer(className, wac));
}
}
+
AnnotationAwareOrderComparator.sort(this.contextInitializers);
for (ApplicationContextInitializer initializer : this.contextInitializers) {
initializer.initialize(wac);
}
}
- /**
- * Post-process the given WebApplicationContext before it is refreshed
- * and activated as context for this servlet.
- * The default implementation is empty. {@code refresh()} will
- * be called automatically after this method returns.
- *
Note that this method is designed to allow subclasses to modify the application
- * context, while {@link #initWebApplicationContext} is designed to allow
- * end-users to modify the context through the use of
- * {@link ApplicationContextInitializer}s.
- * @param wac the configured WebApplicationContext (not refreshed yet)
- * @see #createWebApplicationContext
- * @see #initWebApplicationContext
- * @see ConfigurableWebApplicationContext#refresh()
- */
- protected void postProcessWebApplicationContext(ConfigurableWebApplicationContext wac) {
+ @SuppressWarnings("unchecked")
+ private ApplicationContextInitializer loadInitializer(
+ String className, ConfigurableApplicationContext wac) {
+ try {
+ Class> initializerClass = ClassUtils.forName(className, wac.getClassLoader());
+ Class> initializerContextClass =
+ GenericTypeResolver.resolveTypeArgument(initializerClass, ApplicationContextInitializer.class);
+ if (initializerContextClass != null) {
+ Assert.isAssignable(initializerContextClass, wac.getClass(), String.format(
+ "Could not add context initializer [%s] since its generic parameter [%s] " +
+ "is not assignable from the type of application context used by this " +
+ "framework servlet [%s]: ", initializerClass.getName(), initializerContextClass.getName(),
+ wac.getClass().getName()));
+ }
+ return BeanUtils.instantiateClass(initializerClass, ApplicationContextInitializer.class);
+ }
+ catch (Exception ex) {
+ throw new IllegalArgumentException(String.format("Could not instantiate class [%s] specified " +
+ "via 'contextInitializerClasses' init-param", className), ex);
+ }
}
/**
diff --git a/spring-webmvc/src/test/java/org/springframework/web/context/ContextLoaderTests.java b/spring-webmvc/src/test/java/org/springframework/web/context/ContextLoaderTests.java
index 15a7e36fea4..b8e8630a5df 100644
--- a/spring-webmvc/src/test/java/org/springframework/web/context/ContextLoaderTests.java
+++ b/spring-webmvc/src/test/java/org/springframework/web/context/ContextLoaderTests.java
@@ -16,30 +16,17 @@
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;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
import java.io.FileNotFoundException;
import java.io.IOException;
-
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.junit.Test;
+
import org.springframework.beans.BeansException;
-import org.springframework.tests.sample.beans.TestBean;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanDefinitionStoreException;
-import org.springframework.tests.sample.beans.LifecycleBean;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextException;
@@ -50,11 +37,17 @@ import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertySource;
import org.springframework.mock.web.test.MockServletConfig;
import org.springframework.mock.web.test.MockServletContext;
+import org.springframework.tests.sample.beans.LifecycleBean;
+import org.springframework.tests.sample.beans.TestBean;
import org.springframework.util.StringUtils;
+import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.context.support.XmlWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.SimpleWebApplicationContext;
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
/**
* Tests for {@link ContextLoader} and {@link ContextLoaderListener}.
*
@@ -70,14 +63,14 @@ public final class ContextLoaderTests {
public void testContextLoaderListenerWithDefaultContext() {
MockServletContext sc = new MockServletContext("");
sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
- "/org/springframework/web/context/WEB-INF/applicationContext.xml "
- + "/org/springframework/web/context/WEB-INF/context-addition.xml");
+ "/org/springframework/web/context/WEB-INF/applicationContext.xml " +
+ "/org/springframework/web/context/WEB-INF/context-addition.xml");
ServletContextListener listener = new ContextLoaderListener();
ServletContextEvent event = new ServletContextEvent(sc);
listener.contextInitialized(event);
WebApplicationContext context = (WebApplicationContext) sc.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
assertTrue("Correct WebApplicationContext exposed in ServletContext", context instanceof XmlWebApplicationContext);
- assertTrue(ContextLoader.getCurrentWebApplicationContext() instanceof XmlWebApplicationContext);
+ assertTrue(WebApplicationContextUtils.getRequiredWebApplicationContext(sc) instanceof XmlWebApplicationContext);
LifecycleBean lb = (LifecycleBean) context.getBean("lifecycle");
assertTrue("Has father", context.containsBean("father"));
assertTrue("Has rod", context.containsBean("rod"));
@@ -88,7 +81,7 @@ public final class ContextLoaderTests {
listener.contextDestroyed(event);
assertTrue("Destroyed", lb.isDestroyed());
assertNull(sc.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE));
- assertNull(ContextLoader.getCurrentWebApplicationContext());
+ assertNull(WebApplicationContextUtils.getWebApplicationContext(sc));
}
/**
@@ -104,12 +97,12 @@ public final class ContextLoaderTests {
final MockServletContext sc = new MockServletContext("");
sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
"/org/springframework/web/context/WEB-INF/applicationContext.xml");
- final ServletContextListener listener = new ContextLoaderListener() {
+ ServletContextListener listener = new ContextLoaderListener() {
@Override
- protected void customizeContext(ServletContext servletContext, ConfigurableWebApplicationContext applicationContext) {
- assertNotNull("The ServletContext should not be null.", servletContext);
- assertEquals("Verifying that we received the expected ServletContext.", sc, servletContext);
- assertFalse("The ApplicationContext should not yet have been refreshed.", applicationContext.isActive());
+ protected void customizeContext(ServletContext sc, ConfigurableWebApplicationContext wac) {
+ assertNotNull("The ServletContext should not be null.", sc);
+ assertEquals("Verifying that we received the expected ServletContext.", sc, sc);
+ assertFalse("The ApplicationContext should not yet have been refreshed.", wac.isActive());
buffer.append(expectedContents);
}
};
@@ -118,16 +111,45 @@ public final class ContextLoaderTests {
}
@Test
- public void testContextLoaderListenerWithRegisteredContextInitializer() {
+ public void testContextLoaderListenerWithLocalContextInitializers() {
MockServletContext sc = new MockServletContext("");
sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
"org/springframework/web/context/WEB-INF/ContextLoaderTests-acc-context.xml");
- sc.addInitParameter(ContextLoader.CONTEXT_INITIALIZER_CLASSES_PARAM,
- StringUtils.arrayToCommaDelimitedString(
- new Object[]{TestContextInitializer.class.getName(), TestWebContextInitializer.class.getName()}));
+ sc.addInitParameter(ContextLoader.CONTEXT_INITIALIZER_CLASSES_PARAM, StringUtils.arrayToCommaDelimitedString(
+ new Object[] {TestContextInitializer.class.getName(), TestWebContextInitializer.class.getName()}));
ContextLoaderListener listener = new ContextLoaderListener();
listener.contextInitialized(new ServletContextEvent(sc));
- WebApplicationContext wac = ContextLoaderListener.getCurrentWebApplicationContext();
+ WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
+ TestBean testBean = wac.getBean(TestBean.class);
+ assertThat(testBean.getName(), equalTo("testName"));
+ assertThat(wac.getServletContext().getAttribute("initialized"), notNullValue());
+ }
+
+ @Test
+ public void testContextLoaderListenerWithGlobalContextInitializers() {
+ MockServletContext sc = new MockServletContext("");
+ sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
+ "org/springframework/web/context/WEB-INF/ContextLoaderTests-acc-context.xml");
+ sc.addInitParameter(ContextLoader.GLOBAL_INITIALIZER_CLASSES_PARAM, StringUtils.arrayToCommaDelimitedString(
+ new Object[] {TestContextInitializer.class.getName(), TestWebContextInitializer.class.getName()}));
+ ContextLoaderListener listener = new ContextLoaderListener();
+ listener.contextInitialized(new ServletContextEvent(sc));
+ WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
+ TestBean testBean = wac.getBean(TestBean.class);
+ assertThat(testBean.getName(), equalTo("testName"));
+ assertThat(wac.getServletContext().getAttribute("initialized"), notNullValue());
+ }
+
+ @Test
+ public void testContextLoaderListenerWithMixedContextInitializers() {
+ MockServletContext sc = new MockServletContext("");
+ sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
+ "org/springframework/web/context/WEB-INF/ContextLoaderTests-acc-context.xml");
+ sc.addInitParameter(ContextLoader.CONTEXT_INITIALIZER_CLASSES_PARAM, TestContextInitializer.class.getName());
+ sc.addInitParameter(ContextLoader.GLOBAL_INITIALIZER_CLASSES_PARAM, TestWebContextInitializer.class.getName());
+ ContextLoaderListener listener = new ContextLoaderListener();
+ listener.contextInitialized(new ServletContextEvent(sc));
+ WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
TestBean testBean = wac.getBean(TestBean.class);
assertThat(testBean.getName(), equalTo("testName"));
assertThat(wac.getServletContext().getAttribute("initialized"), notNullValue());
@@ -136,7 +158,7 @@ public final class ContextLoaderTests {
@Test
public void testRegisteredContextInitializerCanAccessServletContextParamsViaEnvironment() {
MockServletContext sc = new MockServletContext("");
- // config file doesn't matter. just a placeholder
+ // config file doesn't matter - just a placeholder
sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
"/org/springframework/web/context/WEB-INF/empty-context.xml");
@@ -153,12 +175,13 @@ public final class ContextLoaderTests {
sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
"/org/springframework/web/context/WEB-INF/empty-context.xml");
sc.addInitParameter(ContextLoader.CONTEXT_INITIALIZER_CLASSES_PARAM,
- StringUtils.arrayToCommaDelimitedString(new Object[]{UnknownContextInitializer.class.getName()}));
+ StringUtils.arrayToCommaDelimitedString(new Object[] {UnknownContextInitializer.class.getName()}));
ContextLoaderListener listener = new ContextLoaderListener();
try {
listener.contextInitialized(new ServletContextEvent(sc));
fail("expected exception");
- } catch (IllegalArgumentException ex) {
+ }
+ catch (IllegalArgumentException ex) {
assertTrue(ex.getMessage().contains("not assignable"));
}
}
@@ -321,7 +344,9 @@ public final class ContextLoaderTests {
}
}
+
private static class TestContextInitializer implements ApplicationContextInitializer {
+
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
@@ -334,7 +359,9 @@ public final class ContextLoaderTests {
}
}
+
private static class TestWebContextInitializer implements ApplicationContextInitializer {
+
@Override
public void initialize(ConfigurableWebApplicationContext applicationContext) {
ServletContext ctx = applicationContext.getServletContext(); // type-safe access to servlet-specific methods
@@ -342,7 +369,9 @@ public final class ContextLoaderTests {
}
}
+
private static class EnvApplicationContextInitializer implements ApplicationContextInitializer {
+
@Override
public void initialize(ConfigurableWebApplicationContext applicationContext) {
// test that ApplicationContextInitializers can access ServletContext properties
@@ -352,11 +381,15 @@ public final class ContextLoaderTests {
}
}
+
private static interface UnknownApplicationContext extends ConfigurableApplicationContext {
+
void unheardOf();
}
+
private static class UnknownContextInitializer implements ApplicationContextInitializer {
+
@Override
public void initialize(UnknownApplicationContext applicationContext) {
applicationContext.unheardOf();