Deregister JDBC drivers when deployed war's ServletContext is destroyed
Closes gh-21221
This commit is contained in:
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.springframework.boot.web.servlet.support;
|
||||
|
||||
import java.sql.Driver;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
@@ -98,7 +101,18 @@ public abstract class SpringBootServletInitializer implements WebApplicationInit
|
||||
// no-op because the application context is already initialized
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent event) {
|
||||
try {
|
||||
super.contextDestroyed(event);
|
||||
}
|
||||
finally {
|
||||
deregisterJdbcDrivers(event.getServletContext());
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
else {
|
||||
this.logger.debug("No ContextLoaderListener registered, as createRootApplicationContext() did not "
|
||||
@@ -106,6 +120,28 @@ public abstract class SpringBootServletInitializer implements WebApplicationInit
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deregisters the JDBC drivers that were registered by the application represented by
|
||||
* the given {@code servletContext}. The default implementation
|
||||
* {@link DriverManager#deregisterDriver(Driver) deregisters} every {@link Driver}
|
||||
* that was loaded by the {@link ServletContext#getClassLoader web application's class
|
||||
* loader}.
|
||||
* @param servletContext the web application's servlet context
|
||||
* @since 2.3.0
|
||||
*/
|
||||
protected void deregisterJdbcDrivers(ServletContext servletContext) {
|
||||
for (Driver driver : Collections.list(DriverManager.getDrivers())) {
|
||||
if (driver.getClass().getClassLoader() == servletContext.getClassLoader()) {
|
||||
try {
|
||||
DriverManager.deregisterDriver(driver);
|
||||
}
|
||||
catch (SQLException ex) {
|
||||
// Continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected WebApplicationContext createRootApplicationContext(ServletContext servletContext) {
|
||||
SpringApplicationBuilder builder = createSpringApplicationBuilder();
|
||||
builder.main(getClass());
|
||||
|
||||
@@ -17,12 +17,18 @@
|
||||
package org.springframework.boot.web.servlet.support;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
@@ -46,6 +52,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Tests for {@link SpringBootServletInitializer}.
|
||||
@@ -142,6 +149,31 @@ class SpringBootServletInitializerTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenServletContextIsDestroyedThenJdbcDriversAreDeregistered() throws ServletException {
|
||||
ServletContext servletContext = mock(ServletContext.class);
|
||||
given(servletContext.getInitParameterNames()).willReturn(new Vector<String>().elements());
|
||||
given(servletContext.getAttributeNames()).willReturn(new Vector<String>().elements());
|
||||
AtomicBoolean driversDeregistered = new AtomicBoolean();
|
||||
new SpringBootServletInitializer() {
|
||||
|
||||
@Override
|
||||
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
|
||||
return builder.sources(Config.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deregisterJdbcDrivers(ServletContext servletContext) {
|
||||
driversDeregistered.set(true);
|
||||
}
|
||||
|
||||
}.onStartup(servletContext);
|
||||
ArgumentCaptor<ServletContextListener> captor = ArgumentCaptor.forClass(ServletContextListener.class);
|
||||
verify(servletContext).addListener(captor.capture());
|
||||
captor.getValue().contextDestroyed(new ServletContextEvent(servletContext));
|
||||
assertThat(driversDeregistered).isTrue();
|
||||
}
|
||||
|
||||
static class PropertySourceVerifyingSpringBootServletInitializer extends SpringBootServletInitializer {
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user