Skip to content

Commit 4d37430

Browse files
committed
Use servlet context that can access classloader
Update `SpringBootServletInitializer` to use the `ServletContext` that was provided to the initial `onStartup` call rather than the one from the `ServletContextEvent`. This allows the `getClassLoader()` call to complete without throwing an `UnsupportedOperationException`. Fixes gh-21684
1 parent 2925326 commit 4d37430

File tree

1 file changed

+37
-21
lines changed

1 file changed

+37
-21
lines changed

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/support/SpringBootServletInitializer.java

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -92,27 +92,9 @@ public void onStartup(ServletContext servletContext) throws ServletException {
9292
// Logger initialization is deferred in case an ordered
9393
// LogServletContextInitializer is being used
9494
this.logger = LogFactory.getLog(getClass());
95-
WebApplicationContext rootAppContext = createRootApplicationContext(servletContext);
96-
if (rootAppContext != null) {
97-
servletContext.addListener(new ContextLoaderListener(rootAppContext) {
98-
99-
@Override
100-
public void contextInitialized(ServletContextEvent event) {
101-
// no-op because the application context is already initialized
102-
}
103-
104-
@Override
105-
public void contextDestroyed(ServletContextEvent event) {
106-
try {
107-
super.contextDestroyed(event);
108-
}
109-
finally {
110-
deregisterJdbcDrivers(event.getServletContext());
111-
}
112-
}
113-
114-
});
115-
95+
WebApplicationContext rootApplicationContext = createRootApplicationContext(servletContext);
96+
if (rootApplicationContext != null) {
97+
servletContext.addListener(new SpringBootContextLoaderListener(rootApplicationContext, servletContext));
11698
}
11799
else {
118100
this.logger.debug("No ContextLoaderListener registered, as createRootApplicationContext() did not "
@@ -212,6 +194,10 @@ protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
212194
return builder;
213195
}
214196

197+
/**
198+
* {@link ApplicationListener} to trigger
199+
* {@link ConfigurableWebEnvironment#initPropertySources(ServletContext, javax.servlet.ServletConfig)}.
200+
*/
215201
private static final class WebEnvironmentPropertySourceInitializer
216202
implements ApplicationListener<ApplicationEnvironmentPreparedEvent>, Ordered {
217203

@@ -236,4 +222,34 @@ public int getOrder() {
236222

237223
}
238224

225+
/**
226+
* {@link ContextLoaderListener} for the initialized context.
227+
*/
228+
private class SpringBootContextLoaderListener extends ContextLoaderListener {
229+
230+
private final ServletContext servletContext;
231+
232+
SpringBootContextLoaderListener(WebApplicationContext applicationContext, ServletContext servletContext) {
233+
super(applicationContext);
234+
this.servletContext = servletContext;
235+
}
236+
237+
@Override
238+
public void contextInitialized(ServletContextEvent event) {
239+
// no-op because the application context is already initialized
240+
}
241+
242+
@Override
243+
public void contextDestroyed(ServletContextEvent event) {
244+
try {
245+
super.contextDestroyed(event);
246+
}
247+
finally {
248+
// Use original context so that the classloader can be accessed
249+
deregisterJdbcDrivers(this.servletContext);
250+
}
251+
}
252+
253+
}
254+
239255
}

0 commit comments

Comments
 (0)