diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/DeploymentManagerHttpHandlerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/DeploymentManagerHttpHandlerFactory.java index 58bd09fcd70..46b9c71a902 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/DeploymentManagerHttpHandlerFactory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/DeploymentManagerHttpHandlerFactory.java @@ -22,6 +22,7 @@ import java.io.IOException; import io.undertow.server.HttpHandler; import io.undertow.server.HttpServerExchange; import io.undertow.servlet.api.DeploymentManager; +import io.undertow.servlet.api.DeploymentManager.State; import jakarta.servlet.ServletException; import org.springframework.util.Assert; @@ -76,12 +77,14 @@ class DeploymentManagerHttpHandlerFactory implements HttpHandlerFactory { @Override public void close() throws IOException { - try { - this.deploymentManager.stop(); - this.deploymentManager.undeploy(); - } - catch (ServletException ex) { - throw new RuntimeException(ex); + if (this.deploymentManager.getState() != State.UNDEPLOYED) { + try { + this.deploymentManager.stop(); + this.deploymentManager.undeploy(); + } + catch (ServletException ex) { + throw new RuntimeException(ex); + } } } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/UndertowServletWebServerFactoryTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/UndertowServletWebServerFactoryTests.java index 46cf2c3bcfe..79692703bf4 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/UndertowServletWebServerFactoryTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/UndertowServletWebServerFactoryTests.java @@ -54,6 +54,7 @@ import org.springframework.boot.web.server.ErrorPage; import org.springframework.boot.web.server.GracefulShutdownResult; import org.springframework.boot.web.server.PortInUseException; import org.springframework.boot.web.server.Shutdown; +import org.springframework.boot.web.server.WebServer; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactory; import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactoryTests; @@ -64,6 +65,7 @@ import org.springframework.test.util.ReflectionTestUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIOException; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.assertj.core.api.Assertions.assertThatNoException; import static org.hamcrest.Matchers.is; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.inOrder; @@ -320,6 +322,16 @@ class UndertowServletWebServerFactoryTests extends AbstractServletWebServerFacto .isInstanceOfAny(SSLException.class, SocketException.class); } + @Test + void multipleCallsToDestroyAreTolerated() { + AbstractServletWebServerFactory factory = getFactory(); + factory.setPort(0); + WebServer webServer = factory.getWebServer(); + webServer.start(); + webServer.destroy(); + assertThatNoException().isThrownBy(webServer::destroy); + } + @Override protected JspServlet getJspServlet() { return null; // Undertow does not support JSPs