Skip to content

Commit 23e58aa

Browse files
committed
Preserve programmatically set context config locations
Prior to this fix, ContextLoader(Listener)'s would overwrite any value set directly against a WebApplicationContext's #setConfigLocation method. This is a likely scenario when using Spring 3.1's new WebApplicationInitializer support. Now a check is performed to ensure that the ContextLoader init-param value is non-null before doing the overwriting. Added tests to ensure that all expected precedence, overwriting and defaulting of context config locations works as expected. Issue: SPR-8510
1 parent ec1b016 commit 23e58aa

File tree

3 files changed

+192
-1
lines changed

3 files changed

+192
-1
lines changed

org.springframework.web.servlet/src/test/java/org/springframework/web/context/ContextLoaderTests.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
* @author Sam Brannen
6262
* @author Chris Beams
6363
* @since 12.08.2003
64+
* @see org.springframework.web.context.support.Spr8510Tests
6465
*/
6566
public final class ContextLoaderTests {
6667

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,10 @@ protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicati
376376

377377
wac.setParent(parent);
378378
wac.setServletContext(sc);
379-
wac.setConfigLocation(sc.getInitParameter(CONFIG_LOCATION_PARAM));
379+
String initParameter = sc.getInitParameter(CONFIG_LOCATION_PARAM);
380+
if (initParameter != null) {
381+
wac.setConfigLocation(initParameter);
382+
}
380383
customizeContext(sc, wac);
381384
wac.refresh();
382385
}
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
/*
2+
* Copyright 2002-2011 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.web.context.support;
18+
19+
import static org.junit.Assert.assertTrue;
20+
import static org.junit.Assert.fail;
21+
22+
import javax.servlet.ServletContextEvent;
23+
24+
import org.junit.Test;
25+
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
26+
import org.springframework.mock.web.MockServletContext;
27+
import org.springframework.web.context.ContextLoader;
28+
import org.springframework.web.context.ContextLoaderListener;
29+
30+
/**
31+
* Tests the interaction between a WebApplicationContext and ContextLoaderListener with
32+
* regard to config location precedence, overriding and defaulting in programmatic
33+
* configuration use cases, e.g. with Spring 3.1's WebApplicationInitializer.
34+
*
35+
* @author Chris Beams
36+
* @since 3.1
37+
* @see org.springframework.web.context.ContextLoaderTests
38+
*/
39+
public class Spr8510Tests {
40+
41+
@Test
42+
public void abstractRefreshableWAC_respectsProgrammaticConfigLocations() {
43+
XmlWebApplicationContext ctx = new XmlWebApplicationContext();
44+
ctx.setConfigLocation("programmatic.xml");
45+
ContextLoaderListener cll = new ContextLoaderListener(ctx);
46+
47+
MockServletContext sc = new MockServletContext();
48+
49+
try {
50+
cll.contextInitialized(new ServletContextEvent(sc));
51+
fail("expected exception");
52+
} catch (Throwable t) {
53+
// assert that an attempt was made to load the correct XML
54+
assertTrue(t.getMessage(), t.getMessage().endsWith(
55+
"Could not open ServletContext resource [/programmatic.xml]"));
56+
}
57+
}
58+
59+
/**
60+
* If a contextConfigLocation init-param has been specified for the ContextLoaderListener,
61+
* then it should take precedence. This is generally not a recommended practice, but
62+
* when it does happen, the init-param should be considered more specific than the
63+
* programmatic configuration, given that it still quite possibly externalized in
64+
* hybrid web.xml + WebApplicationInitializer cases.
65+
*/
66+
@Test
67+
public void abstractRefreshableWAC_respectsInitParam_overProgrammaticConfigLocations() {
68+
XmlWebApplicationContext ctx = new XmlWebApplicationContext();
69+
ctx.setConfigLocation("programmatic.xml");
70+
ContextLoaderListener cll = new ContextLoaderListener(ctx);
71+
72+
MockServletContext sc = new MockServletContext();
73+
sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM, "from-init-param.xml");
74+
75+
try {
76+
cll.contextInitialized(new ServletContextEvent(sc));
77+
fail("expected exception");
78+
} catch (Throwable t) {
79+
// assert that an attempt was made to load the correct XML
80+
assertTrue(t.getMessage(), t.getMessage().endsWith(
81+
"Could not open ServletContext resource [/from-init-param.xml]"));
82+
}
83+
}
84+
85+
/**
86+
* If setConfigLocation has not been called explicitly against the application context,
87+
* then fall back to the ContextLoaderListener init-param if present.
88+
*/
89+
@Test
90+
public void abstractRefreshableWAC_fallsBackToInitParam() {
91+
XmlWebApplicationContext ctx = new XmlWebApplicationContext();
92+
//ctx.setConfigLocation("programmatic.xml"); // nothing set programmatically
93+
ContextLoaderListener cll = new ContextLoaderListener(ctx);
94+
95+
MockServletContext sc = new MockServletContext();
96+
sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM, "from-init-param.xml");
97+
98+
try {
99+
cll.contextInitialized(new ServletContextEvent(sc));
100+
fail("expected exception");
101+
} catch (Throwable t) {
102+
// assert that an attempt was made to load the correct XML
103+
assertTrue(t.getMessage().endsWith(
104+
"Could not open ServletContext resource [/from-init-param.xml]"));
105+
}
106+
}
107+
108+
/**
109+
* Ensure that any custom default locations are still respected.
110+
*/
111+
@Test
112+
public void customAbstractRefreshableWAC_fallsBackToInitParam() {
113+
XmlWebApplicationContext ctx = new XmlWebApplicationContext() {
114+
@Override
115+
protected String[] getDefaultConfigLocations() {
116+
return new String[] { "/WEB-INF/custom.xml" };
117+
}
118+
};
119+
//ctx.setConfigLocation("programmatic.xml"); // nothing set programmatically
120+
ContextLoaderListener cll = new ContextLoaderListener(ctx);
121+
122+
MockServletContext sc = new MockServletContext();
123+
sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM, "from-init-param.xml");
124+
125+
try {
126+
cll.contextInitialized(new ServletContextEvent(sc));
127+
fail("expected exception");
128+
} catch (Throwable t) {
129+
// assert that an attempt was made to load the correct XML
130+
System.out.println(t.getMessage());
131+
assertTrue(t.getMessage().endsWith(
132+
"Could not open ServletContext resource [/from-init-param.xml]"));
133+
}
134+
}
135+
136+
/**
137+
* If context config locations have been specified neither against the application
138+
* context nor the context loader listener, then fall back to default values.
139+
*/
140+
@Test
141+
public void abstractRefreshableWAC_fallsBackToConventionBasedNaming() {
142+
XmlWebApplicationContext ctx = new XmlWebApplicationContext();
143+
//ctx.setConfigLocation("programmatic.xml"); // nothing set programmatically
144+
ContextLoaderListener cll = new ContextLoaderListener(ctx);
145+
146+
MockServletContext sc = new MockServletContext();
147+
// no init-param set
148+
//sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM, "from-init-param.xml");
149+
150+
try {
151+
cll.contextInitialized(new ServletContextEvent(sc));
152+
fail("expected exception");
153+
} catch (Throwable t) {
154+
// assert that an attempt was made to load the correct XML
155+
System.out.println(t.getMessage());
156+
assertTrue(t.getMessage().endsWith(
157+
"Could not open ServletContext resource [/WEB-INF/applicationContext.xml]"));
158+
}
159+
}
160+
161+
/**
162+
* Ensure that ContextLoaderListener and GenericWebApplicationContext interact nicely.
163+
*/
164+
@Test
165+
public void genericWAC() {
166+
GenericWebApplicationContext ctx = new GenericWebApplicationContext();
167+
ContextLoaderListener cll = new ContextLoaderListener(ctx);
168+
169+
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(ctx);
170+
scanner.scan("bogus.pkg");
171+
172+
cll.contextInitialized(new ServletContextEvent(new MockServletContext()));
173+
}
174+
175+
/**
176+
* Ensure that ContextLoaderListener and AnnotationConfigApplicationContext interact nicely.
177+
*/
178+
@Test
179+
public void annotationConfigWAC() {
180+
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
181+
182+
ctx.scan("does.not.matter");
183+
184+
ContextLoaderListener cll = new ContextLoaderListener(ctx);
185+
cll.contextInitialized(new ServletContextEvent(new MockServletContext()));
186+
}
187+
}

0 commit comments

Comments
 (0)