diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java index c0d23591c5..df3ca5f65f 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java @@ -56,6 +56,7 @@ import org.eclipse.jetty.servlets.gzip.GzipHandler; import org.eclipse.jetty.util.resource.JarResource; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.eclipse.jetty.util.thread.ThreadPool; import org.eclipse.jetty.webapp.AbstractConfiguration; import org.eclipse.jetty.webapp.Configuration; import org.eclipse.jetty.webapp.WebAppContext; @@ -92,6 +93,7 @@ import org.springframework.util.StringUtils; * @author Andy Wilkinson * @author EddĂș MelĂ©ndez * @author Venil Noronha + * @author Henri Kerola * @see #setPort(int) * @see #setConfigurations(Collection) * @see JettyEmbeddedServletContainer @@ -125,6 +127,8 @@ public class JettyEmbeddedServletContainerFactory private ResourceLoader resourceLoader; + private ThreadPool threadPool; + /** * Create a new {@link JettyEmbeddedServletContainerFactory} instance. */ @@ -178,7 +182,13 @@ public class JettyEmbeddedServletContainerFactory } private Server createServer(InetSocketAddress address) { - Server server = new Server(); + Server server; + if (ClassUtils.hasConstructor(Server.class, ThreadPool.class)) { + server = new Jetty9ServerFactory().createServer(getThreadPool()); + } + else { + server = new Jetty8ServerFactory().createServer(getThreadPool()); + } server.setConnectors(new Connector[] { createConnector(address, server) }); return server; } @@ -596,6 +606,24 @@ public class JettyEmbeddedServletContainerFactory this.configurations.addAll(Arrays.asList(configurations)); } + /** + * Returns a Jetty {@link ThreadPool} that should be used by the {@link Server}. + * @return a Jetty {@link ThreadPool} or {@code null} + */ + public ThreadPool getThreadPool() { + return this.threadPool; + } + + /** + * Set a Jetty {@link ThreadPool} that should be used by the {@link Server}. + * If set to {@code null} (default), the {@link Server} creates + * a {@link ThreadPool} implicitly. + * @param threadPool a Jetty ThreadPool to be used + */ + public void setThreadPool(ThreadPool threadPool) { + this.threadPool = threadPool; + } + private void addJettyErrorPages(ErrorHandler errorHandler, Collection errorPages) { if (errorHandler instanceof ErrorPageErrorHandler) { @@ -858,4 +886,37 @@ public class JettyEmbeddedServletContainerFactory } + private interface ServerFactory { + + Server createServer(ThreadPool threadPool); + + } + + private static class Jetty8ServerFactory implements ServerFactory { + + @Override + public Server createServer(ThreadPool threadPool) { + Server server = new Server(); + try { + ReflectionUtils.findMethod(Server.class, "setThreadPool", ThreadPool.class) + .invoke(server, threadPool); + } + catch (Exception e) { + throw new RuntimeException("Failed to configure Jetty 8 ThreadPool", e); + } + return server; + } + + } + + private static class Jetty9ServerFactory implements ServerFactory { + + @Override + public Server createServer(ThreadPool threadPool) { + Server server = new Server(threadPool); + return server; + } + + } + } diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactoryTests.java b/spring-boot/src/test/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactoryTests.java index 803e4ce2f0..33c4608d8f 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactoryTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactoryTests.java @@ -34,6 +34,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.ThreadPool; import org.eclipse.jetty.webapp.Configuration; import org.eclipse.jetty.webapp.WebAppContext; import org.junit.Test; @@ -58,6 +59,7 @@ import static org.mockito.Mockito.mock; * @author Phillip Webb * @author Dave Syer * @author Andy Wilkinson + * @author Henri Kerola */ public class JettyEmbeddedServletContainerFactoryTests extends AbstractEmbeddedServletContainerFactoryTests { @@ -256,6 +258,29 @@ public class JettyEmbeddedServletContainerFactoryTests assertForwardHeaderIsUsed(factory); } + @Test + public void threadPool() throws Exception { + JettyEmbeddedServletContainerFactory factory = getFactory(); + + ThreadPool threadPool = mock(ThreadPool.class); + factory.setThreadPool(threadPool); + + JettyEmbeddedServletContainer servletContainer = (JettyEmbeddedServletContainer) factory.getEmbeddedServletContainer(); + assertThat(servletContainer.getServer().getThreadPool()).isSameAs(threadPool); + } + + @Test + public void nullThreadPool() throws Exception { + JettyEmbeddedServletContainerFactory factory = getFactory(); + + factory.setThreadPool(null); + + assertThat(factory.getThreadPool()).isNull(); + + JettyEmbeddedServletContainer servletContainer = (JettyEmbeddedServletContainer) factory.getEmbeddedServletContainer(); + assertThat(servletContainer.getServer().getThreadPool()).isNotNull(); + } + @Override @SuppressWarnings("serial") // Workaround for Jetty issue - https://bugs.eclipse.org/bugs/show_bug.cgi?id=470646