diff --git a/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyWebServer.java b/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyWebServer.java index f25bfe6fba..3d2f7fb223 100644 --- a/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyWebServer.java +++ b/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyWebServer.java @@ -27,6 +27,7 @@ import org.eclipse.jetty.server.NetworkConnector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.server.handler.HandlerWrapper; +import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.springframework.boot.web.server.PortInUseException; import org.springframework.boot.web.server.WebServer; @@ -83,11 +84,21 @@ public class JettyWebServer implements WebServer { private void initialize() { synchronized (this.monitor) { try { - // Cache and clear the connectors to prevent requests being handled before - // the application context is ready + // Cache the connectors and then remove them to prevent requests being + // handled before the application context is ready. this.connectors = this.server.getConnectors(); - this.server.setConnectors(null); + this.server.addBean(new AbstractLifeCycle() { + @Override + protected void doStart() throws Exception { + for (Connector connector : JettyWebServer.this.connectors) { + Assert.state(connector.isStopped(), "Connector " + connector + + " has been started prematurely"); + } + JettyWebServer.this.server.setConnectors(null); + } + + }); // Start the server so that the ServletContext is available this.server.start(); this.server.setStopAtShutdown(false); diff --git a/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactoryTests.java b/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactoryTests.java index ddc4b0f357..c354530c78 100644 --- a/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactoryTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactoryTests.java @@ -36,6 +36,7 @@ import org.eclipse.jetty.server.SslConnectionFactory; import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.server.handler.HandlerWrapper; import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.eclipse.jetty.util.thread.ThreadPool; import org.eclipse.jetty.webapp.Configuration; import org.eclipse.jetty.webapp.WebAppContext; @@ -51,6 +52,7 @@ import org.springframework.boot.web.servlet.server.AbstractServletWebServerFacto import org.springframework.http.HttpHeaders; import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.CoreMatchers.instanceOf; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; @@ -277,6 +279,22 @@ public class JettyServletWebServerFactoryTests .isSameAs(threadPool); } + @Test + public void startFailsWhenThreadPoolIsTooSmall() throws Exception { + JettyServletWebServerFactory factory = getFactory(); + factory.addServerCustomizers(new JettyServerCustomizer() { + + @Override + public void customize(Server server) { + QueuedThreadPool threadPool = server.getBean(QueuedThreadPool.class); + threadPool.setMaxThreads(2); + threadPool.setMinThreads(2); + } + }); + this.thrown.expectCause(instanceOf(IllegalStateException.class)); + factory.getWebServer().start(); + } + @Override @SuppressWarnings("serial") // Workaround for Jetty issue - https://bugs.eclipse.org/bugs/show_bug.cgi?id=470646