Delay ServletContext destruction until Undertow is destroyed

Previously, all destruction was done in the stop method including
closing any Closeables registered with the server. One of these
Closeables managed the lifecycle of the DeploymentManager for the
servlet deployment. Closing it made the servlet context unusable
in `@PreDestroy` methods and upon restart.

This commit moves the closing of the registered Closeables into
destroy(). This allows `@PreDestory` methods to use the
ServletContext. It also allows the server to be stopped and then
restarted without making the ServletContext unusable as it's left
running while the server itself is stopped and not accepting
requests.

Fixes gh-47141
This commit is contained in:
Andy Wilkinson
2025-11-11 17:00:48 +00:00
parent 8249929b68
commit a21bfc2ff5
2 changed files with 13 additions and 15 deletions
@@ -279,9 +279,6 @@ public class UndertowWebServer implements WebServer {
}
try {
this.undertow.stop();
for (Closeable closeable : this.closeables) {
closeable.close();
}
}
catch (Exception ex) {
throw new WebServerException("Unable to stop Undertow", ex);
@@ -289,6 +286,19 @@ public class UndertowWebServer implements WebServer {
}
}
@Override
public void destroy() {
stop();
try {
for (Closeable closeable : this.closeables) {
closeable.close();
}
}
catch (IOException ex) {
throw new WebServerException("Unable to destroy Undertow", ex);
}
}
@Override
public int getPort() {
List<Port> ports = getActualPorts();
@@ -255,18 +255,6 @@ class UndertowServletWebServerFactoryTests extends AbstractServletWebServerFacto
super.portClashOfSecondaryConnectorResultsInPortInUseException();
}
@Test
@Override
@Disabled("Restart after stop is not supported with Undertow")
protected void restartAfterStop() {
}
@Test
@Override
@Disabled("Undertow's architecture prevents separating stop and destroy")
protected void servletContextListenerContextDestroyedIsNotCalledWhenContainerIsStopped() {
}
private void testAccessLog(String prefix, String suffix, String expectedFile)
throws IOException, URISyntaxException {
UndertowServletWebServerFactory factory = getFactory();