Browse Source

Introduced "globalInitializerClasses" next to the existing "contextInitializerClasses", applying to FrameworkServlets as well

Issue: SPR-11314
pull/438/merge
Juergen Hoeller 11 years ago
parent
commit
91881ff036
  1. 192
      spring-web/src/main/java/org/springframework/web/context/ContextLoader.java
  2. 145
      spring-webmvc/src/main/java/org/springframework/web/servlet/FrameworkServlet.java
  3. 95
      spring-webmvc/src/test/java/org/springframework/web/context/ContextLoaderTests.java

192
spring-web/src/main/java/org/springframework/web/context/ContextLoader.java

@ -77,8 +77,8 @@ import org.springframework.util.StringUtils; @@ -77,8 +77,8 @@ import org.springframework.util.StringUtils;
*
* <p>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; @@ -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 { @@ -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 { @@ -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 { @@ -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 <em>refreshed</em>.
* <p>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.
* <p>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<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>> initializerClasses =
determineContextInitializerClasses(sc);
if (initializerClasses.isEmpty()) {
// no ApplicationContextInitializers have been declared -> nothing to do
return;
}
ArrayList<ApplicationContextInitializer<ConfigurableApplicationContext>> initializerInstances =
new ArrayList<ApplicationContextInitializer<ConfigurableApplicationContext>>();
for (Class<ApplicationContextInitializer<ConfigurableApplicationContext>> 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<ConfigurableApplicationContext> 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 { @@ -418,80 +488,38 @@ public class ContextLoader {
* @param servletContext current servlet context
* @see #CONTEXT_INITIALIZER_CLASSES_PARAM
*/
@SuppressWarnings("unchecked")
protected List<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>>
determineContextInitializerClasses(ServletContext servletContext) {
String classNames = servletContext.getInitParameter(CONTEXT_INITIALIZER_CLASSES_PARAM);
List<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>> classes =
new ArrayList<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>>();
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<ApplicationContextInitializer<ConfigurableApplicationContext>>)clazz);
}
catch (ClassNotFoundException ex) {
throw new ApplicationContextException(
"Failed to load context initializer class [" + className + "]", ex);
}
}
}
return classes;
}
new ArrayList<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>>();
/**
* Customize the {@link ConfigurableWebApplicationContext} created by this
* ContextLoader after config locations have been supplied to the context
* but before the context is <em>refreshed</em>.
* <p>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.
* <p>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<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>> 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<ApplicationContextInitializer<ConfigurableApplicationContext>> initializerInstances =
new ArrayList<ApplicationContextInitializer<ConfigurableApplicationContext>>();
for (Class<ApplicationContextInitializer<ConfigurableApplicationContext>> 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<ConfigurableApplicationContext> initializer : initializerInstances) {
initializer.initialize(applicationContext);
@SuppressWarnings("unchecked")
private Class<ApplicationContextInitializer<ConfigurableApplicationContext>> loadInitializerClass(String className) {
try {
Class<?> clazz = ClassUtils.forName(className, ClassUtils.getDefaultClassLoader());
Assert.isAssignable(ApplicationContextInitializer.class, clazz);
return (Class<ApplicationContextInitializer<ConfigurableApplicationContext>>) clazz;
}
catch (ClassNotFoundException ex) {
throw new ApplicationContextException("Failed to load context initializer class [" + className + "]", ex);
}
}

145
spring-webmvc/src/main/java/org/springframework/web/servlet/FrameworkServlet.java

@ -20,7 +20,6 @@ import java.io.IOException; @@ -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; @@ -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 @@ -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<ApplicationContextInitializer<ConfigurableApplicationContext>> contextInitializers =
new ArrayList<ApplicationContextInitializer<ConfigurableApplicationContext>>();
/** 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 @@ -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<ApplicationContextInitializer<ConfigurableApplicationContext>> contextInitializers =
new ArrayList<ApplicationContextInitializer<ConfigurableApplicationContext>>();
/**
* Create a new {@code FrameworkServlet} that will create its own internal web
@ -340,13 +342,19 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic @@ -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 @@ -355,7 +363,6 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
* @see #configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext)
* @see #applyInitializers(ConfigurableApplicationContext)
*/
@SuppressWarnings("unchecked")
public void setContextInitializers(ApplicationContextInitializer<ConfigurableApplicationContext>... contextInitializers) {
for (ApplicationContextInitializer<ConfigurableApplicationContext> initializer : contextInitializers) {
this.contextInitializers.add(initializer);
@ -363,19 +370,13 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic @@ -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 @@ -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 @@ -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.
* <p>The default implementation is empty. {@code refresh()} will
* be called automatically after this method returns.
* <p>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.
* <p>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<ConfigurableApplicationContext> 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<ConfigurableApplicationContext> initializer : this.contextInitializers) {
initializer.initialize(wac);
}
}
/**
* Post-process the given WebApplicationContext before it is refreshed
* and activated as context for this servlet.
* <p>The default implementation is empty. {@code refresh()} will
* be called automatically after this method returns.
* <p>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<ConfigurableApplicationContext> 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);
}
}
/**

95
spring-webmvc/src/test/java/org/springframework/web/context/ContextLoaderTests.java

@ -16,30 +16,17 @@ @@ -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; @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -321,7 +344,9 @@ public final class ContextLoaderTests {
}
}
private static class TestContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
@ -334,7 +359,9 @@ public final class ContextLoaderTests { @@ -334,7 +359,9 @@ public final class ContextLoaderTests {
}
}
private static class TestWebContextInitializer implements ApplicationContextInitializer<ConfigurableWebApplicationContext> {
@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 { @@ -342,7 +369,9 @@ public final class ContextLoaderTests {
}
}
private static class EnvApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableWebApplicationContext> {
@Override
public void initialize(ConfigurableWebApplicationContext applicationContext) {
// test that ApplicationContextInitializers can access ServletContext properties
@ -352,11 +381,15 @@ public final class ContextLoaderTests { @@ -352,11 +381,15 @@ public final class ContextLoaderTests {
}
}
private static interface UnknownApplicationContext extends ConfigurableApplicationContext {
void unheardOf();
}
private static class UnknownContextInitializer implements ApplicationContextInitializer<UnknownApplicationContext> {
@Override
public void initialize(UnknownApplicationContext applicationContext) {
applicationContext.unheardOf();

Loading…
Cancel
Save