Skip to content

Commit b720804

Browse files
committed
ContextLoader properly detects pre-refreshed WebApplicationContext
Issue: SPR-9996
1 parent 1e88870 commit b720804

File tree

1 file changed

+27
-21
lines changed

1 file changed

+27
-21
lines changed

org.springframework.web/src/main/java/org/springframework/web/context/ContextLoader.java

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,11 +23,11 @@
2323
import java.util.Map;
2424
import java.util.Properties;
2525
import java.util.concurrent.ConcurrentHashMap;
26-
2726
import javax.servlet.ServletContext;
2827

2928
import org.apache.commons.logging.Log;
3029
import org.apache.commons.logging.LogFactory;
30+
3131
import org.springframework.beans.BeanUtils;
3232
import org.springframework.beans.factory.access.BeanFactoryLocator;
3333
import org.springframework.beans.factory.access.BeanFactoryReference;
@@ -50,7 +50,7 @@
5050
* Called by {@link ContextLoaderListener}.
5151
*
5252
* <p>Looks for a {@link #CONTEXT_CLASS_PARAM "contextClass"} parameter
53-
* at the <code>web.xml</code> context-param level to specify the context
53+
* at the {@code web.xml} context-param level to specify the context
5454
* class type, falling back to the default of
5555
* {@link org.springframework.web.context.support.XmlWebApplicationContext}
5656
* if not found. With the default ContextLoader implementation, any context class
@@ -119,29 +119,29 @@ public class ContextLoader {
119119
public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation";
120120

121121
/**
122-
* Optional servlet context parameter (i.e., "<code>locatorFactorySelector</code>")
122+
* Optional servlet context parameter (i.e., "{@code locatorFactorySelector}")
123123
* used only when obtaining a parent context using the default implementation
124124
* of {@link #loadParentContext(ServletContext servletContext)}.
125125
* Specifies the 'selector' used in the
126126
* {@link ContextSingletonBeanFactoryLocator#getInstance(String selector)}
127127
* method call, which is used to obtain the BeanFactoryLocator instance from
128128
* which the parent context is obtained.
129-
* <p>The default is <code>classpath*:beanRefContext.xml</code>,
129+
* <p>The default is {@code classpath*:beanRefContext.xml},
130130
* matching the default applied for the
131131
* {@link ContextSingletonBeanFactoryLocator#getInstance()} method.
132132
* Supplying the "parentContextKey" parameter is sufficient in this case.
133133
*/
134134
public static final String LOCATOR_FACTORY_SELECTOR_PARAM = "locatorFactorySelector";
135135

136136
/**
137-
* Optional servlet context parameter (i.e., "<code>parentContextKey</code>")
137+
* Optional servlet context parameter (i.e., "{@code parentContextKey}")
138138
* used only when obtaining a parent context using the default implementation
139139
* of {@link #loadParentContext(ServletContext servletContext)}.
140140
* Specifies the 'factoryKey' used in the
141141
* {@link BeanFactoryLocator#useBeanFactory(String factoryKey)} method call,
142142
* obtaining the parent application context from the BeanFactoryLocator instance.
143143
* <p>Supplying this "parentContextKey" parameter is sufficient when relying
144-
* on the default <code>classpath*:beanRefContext.xml</code> selector for
144+
* on the default {@code classpath*:beanRefContext.xml} selector for
145145
* candidate factory references.
146146
*/
147147
public static final String LOCATOR_FACTORY_KEY_PARAM = "parentContextKey";
@@ -280,7 +280,18 @@ public WebApplicationContext initWebApplicationContext(ServletContext servletCon
280280
this.context = createWebApplicationContext(servletContext);
281281
}
282282
if (this.context instanceof ConfigurableWebApplicationContext) {
283-
configureAndRefreshWebApplicationContext((ConfigurableWebApplicationContext)this.context, servletContext);
283+
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
284+
if (!cwac.isActive()) {
285+
// The context has not yet been refreshed -> provide services such as
286+
// setting the parent context, setting the application context id, etc
287+
if (cwac.getParent() == null) {
288+
// The context instance was injected without an explicit parent ->
289+
// determine parent for root web application context, if any.
290+
ApplicationContext parent = loadParentContext(servletContext);
291+
cwac.setParent(parent);
292+
}
293+
configureAndRefreshWebApplicationContext(cwac, servletContext);
294+
}
284295
}
285296
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
286297

@@ -333,9 +344,7 @@ protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
333344
throw new ApplicationContextException("Custom context class [" + contextClass.getName() +
334345
"] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");
335346
}
336-
ConfigurableWebApplicationContext wac =
337-
(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
338-
return wac;
347+
return (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
339348
}
340349

341350
/**
@@ -370,10 +379,6 @@ protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicati
370379
}
371380
}
372381

373-
// Determine parent for root web application context, if any.
374-
ApplicationContext parent = loadParentContext(sc);
375-
376-
wac.setParent(parent);
377382
wac.setServletContext(sc);
378383
String initParameter = sc.getInitParameter(CONFIG_LOCATION_PARAM);
379384
if (initParameter != null) {
@@ -470,17 +475,18 @@ protected void customizeContext(ServletContext servletContext, ConfigurableWebAp
470475
return;
471476
}
472477

478+
Class<?> contextClass = applicationContext.getClass();
473479
ArrayList<ApplicationContextInitializer<ConfigurableApplicationContext>> initializerInstances =
474-
new ArrayList<ApplicationContextInitializer<ConfigurableApplicationContext>>();
480+
new ArrayList<ApplicationContextInitializer<ConfigurableApplicationContext>>();
475481

476482
for (Class<ApplicationContextInitializer<ConfigurableApplicationContext>> initializerClass : initializerClasses) {
477-
Class<?> contextClass = applicationContext.getClass();
478483
Class<?> initializerContextClass =
479-
GenericTypeResolver.resolveTypeArgument(initializerClass, ApplicationContextInitializer.class);
484+
GenericTypeResolver.resolveTypeArgument(initializerClass, ApplicationContextInitializer.class);
480485
Assert.isAssignable(initializerContextClass, contextClass, String.format(
481486
"Could not add context initializer [%s] as its generic parameter [%s] " +
482487
"is not assignable from the type of application context used by this " +
483-
"context loader [%s]", initializerClass.getName(), initializerContextClass, contextClass));
488+
"context loader [%s]: ", initializerClass.getName(), initializerContextClass.getName(),
489+
contextClass.getName()));
484490
initializerInstances.add(BeanUtils.instantiateClass(initializerClass));
485491
}
486492

@@ -509,7 +515,7 @@ protected void customizeContext(ServletContext servletContext, ConfigurableWebAp
509515
* which will be shared by all other users of ContextsingletonBeanFactoryLocator
510516
* which also use the same configuration parameters.
511517
* @param servletContext current servlet context
512-
* @return the parent application context, or <code>null</code> if none
518+
* @return the parent application context, or {@code null} if none
513519
* @see org.springframework.context.access.ContextSingletonBeanFactoryLocator
514520
*/
515521
protected ApplicationContext loadParentContext(ServletContext servletContext) {
@@ -568,7 +574,7 @@ else if (ccl != null) {
568574
* Obtain the Spring root web application context for the current thread
569575
* (i.e. for the current thread's context ClassLoader, which needs to be
570576
* the web application's ClassLoader).
571-
* @return the current root web application context, or <code>null</code>
577+
* @return the current root web application context, or {@code null}
572578
* if none found
573579
* @see org.springframework.web.context.support.SpringBeanAutowiringSupport
574580
*/

0 commit comments

Comments
 (0)