diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java index 3e5eae2a35..45e86d0f68 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java @@ -1129,6 +1129,11 @@ public class ServerProperties { */ private Boolean directBuffers; + /** + * Whether servlet filters should be initialized on startup. + */ + private boolean eagerFilterInit = true; + private final Accesslog accesslog = new Accesslog(); public long getMaxHttpPostSize() { @@ -1171,6 +1176,14 @@ public class ServerProperties { this.directBuffers = directBuffers; } + public boolean isEagerFilterInit() { + return this.eagerFilterInit; + } + + public void setEagerFilterInit(boolean eagerFilterInit) { + this.eagerFilterInit = eagerFilterInit; + } + public Accesslog getAccesslog() { return this.accesslog; } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/DefaultServletWebServerFactoryCustomizer.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/DefaultServletWebServerFactoryCustomizer.java index ec79263a22..3861215987 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/DefaultServletWebServerFactoryCustomizer.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/DefaultServletWebServerFactoryCustomizer.java @@ -472,11 +472,12 @@ public class DefaultServletWebServerFactoryCustomizer customizeMaxHttpPostSize(factory, undertowProperties.getMaxHttpPostSize()); } - if (serverProperties.getConnectionTimeout() != null) { customizeConnectionTimeout(factory, serverProperties.getConnectionTimeout()); } + factory.addDeploymentInfoCustomizers((deploymentInfo) -> deploymentInfo + .setEagerFilterInit(undertowProperties.isEagerFilterInit())); } private static void customizeConnectionTimeout( diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index 66c1f058f4..d81cb8c53f 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -246,6 +246,7 @@ content into your application; rather pick only the properties that you need. server.undertow.buffer-size= # Size of each buffer in bytes. server.undertow.direct-buffers= # Allocate buffers outside the Java heap. server.undertow.io-threads= # Number of I/O threads to create for the worker. + server.undertow.eager-filter-init=true # Whether servlet filters should be initialized on startup. server.undertow.max-http-post-size=0 # Maximum size in bytes of the HTTP post content. server.undertow.worker-threads= # Number of worker threads. diff --git a/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowServletWebServerFactory.java b/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowServletWebServerFactory.java index be6245e4d0..660459345e 100644 --- a/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowServletWebServerFactory.java +++ b/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowServletWebServerFactory.java @@ -137,6 +137,8 @@ public class UndertowServletWebServerFactory extends AbstractServletWebServerFac private boolean useForwardHeaders; + private boolean eagerInitFilters = true; + /** * Create a new {@link UndertowServletWebServerFactory} instance. */ @@ -392,6 +394,7 @@ public class UndertowServletWebServerFactory extends AbstractServletWebServerFac configureErrorPages(deployment); deployment.setServletStackTraces(ServletStackTraces.NONE); deployment.setResourceManager(getDocumentRootResourceManager()); + deployment.setEagerFilterInit(this.eagerInitFilters); configureMimeMappings(deployment); for (UndertowDeploymentInfoCustomizer customizer : this.deploymentInfoCustomizers) { customizer.customize(deployment); @@ -637,6 +640,25 @@ public class UndertowServletWebServerFactory extends AbstractServletWebServerFac this.useForwardHeaders = useForwardHeaders; } + /** + * Return if filters should be initialized eagerly. + * @return {@code true} if filters are initialized eagerly, otherwise {@code false}. + * @since 2.0.0 + */ + public boolean isEagerInitFilters() { + return this.eagerInitFilters; + } + + /** + * Set whether filters should be initialized eagerly. + * @param eagerInitFilters {@code true} if filters are initialized eagerly, otherwise + * {@code false}. + * @since 2.0.0 + */ + public void setEagerInitFilters(boolean eagerInitFilters) { + this.eagerInitFilters = eagerInitFilters; + } + /** * {@link ResourceManager} that exposes resource in {@code META-INF/resources} * directory of nested (in {@code BOOT-INF/lib} or {@code WEB-INF/lib}) jars. 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 39d88af3be..ddc4b0f357 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 @@ -23,13 +23,7 @@ import java.util.Locale; import java.util.Map; import java.util.concurrent.TimeUnit; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletContext; import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -51,8 +45,6 @@ import org.mockito.InOrder; import org.springframework.boot.web.server.Compression; import org.springframework.boot.web.server.PortInUseException; import org.springframework.boot.web.server.Ssl; -import org.springframework.boot.web.server.WebServerException; -import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactory; import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactoryTests; @@ -285,38 +277,6 @@ public class JettyServletWebServerFactoryTests .isSameAs(threadPool); } - @Test - public void faultyFilterCausesStartFailure() throws Exception { - JettyServletWebServerFactory factory = getFactory(); - factory.addInitializers(new ServletContextInitializer() { - - @Override - public void onStartup(ServletContext servletContext) throws ServletException { - servletContext.addFilter("faulty", new Filter() { - - @Override - public void init(FilterConfig filterConfig) throws ServletException { - throw new ServletException("Faulty filter"); - } - - @Override - public void doFilter(ServletRequest request, ServletResponse response, - FilterChain chain) throws IOException, ServletException { - chain.doFilter(request, response); - } - - @Override - public void destroy() { - } - - }); - } - - }); - this.thrown.expect(WebServerException.class); - factory.getWebServer().start(); - } - @Override @SuppressWarnings("serial") // Workaround for Jetty issue - https://bugs.eclipse.org/bugs/show_bug.cgi?id=470646 diff --git a/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactoryTests.java b/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactoryTests.java index f96af9f9c1..8dd392b801 100644 --- a/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactoryTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactoryTests.java @@ -26,13 +26,7 @@ import java.util.concurrent.TimeUnit; import javax.naming.InitialContext; import javax.naming.NamingException; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletContext; import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; import org.apache.catalina.Container; import org.apache.catalina.Context; @@ -57,7 +51,6 @@ import org.mockito.InOrder; import org.springframework.boot.testutil.InternalOutputCapture; import org.springframework.boot.web.server.Ssl; import org.springframework.boot.web.server.WebServerException; -import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactory; import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactoryTests; import org.springframework.test.util.ReflectionTestUtils; @@ -451,38 +444,6 @@ public class TomcatServletWebServerFactoryTests assertThat(sessionIdGenerator.getJvmRoute()).isEqualTo("test"); } - @Test - public void faultyFilterCausesStartFailure() throws Exception { - TomcatServletWebServerFactory factory = getFactory(); - factory.addInitializers(new ServletContextInitializer() { - - @Override - public void onStartup(ServletContext servletContext) throws ServletException { - servletContext.addFilter("faulty", new Filter() { - - @Override - public void init(FilterConfig filterConfig) throws ServletException { - throw new ServletException("Faulty filter"); - } - - @Override - public void doFilter(ServletRequest request, ServletResponse response, - FilterChain chain) throws IOException, ServletException { - chain.doFilter(request, response); - } - - @Override - public void destroy() { - } - - }); - } - - }); - this.thrown.expect(WebServerException.class); - factory.getWebServer().start(); - } - @Override protected JspServlet getJspServlet() throws ServletException { Tomcat tomcat = ((TomcatWebServer) this.webServer).getTomcat(); diff --git a/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java b/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java index 0f4e798dba..71d69cdb87 100644 --- a/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java @@ -50,6 +50,9 @@ import java.util.zip.GZIPInputStream; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLException; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; import javax.servlet.GenericServlet; import javax.servlet.ServletContext; import javax.servlet.ServletException; @@ -88,6 +91,7 @@ import org.springframework.boot.web.server.Ssl; import org.springframework.boot.web.server.Ssl.ClientAuth; import org.springframework.boot.web.server.SslStoreProvider; import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.WebServerException; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.boot.web.servlet.ServletRegistrationBean; @@ -944,6 +948,38 @@ public abstract class AbstractServletWebServerFactoryTests { assertThat(options.getDevelopment()).isEqualTo(false); } + @Test + public void faultyFilterCausesStartFailure() throws Exception { + AbstractServletWebServerFactory factory = getFactory(); + factory.addInitializers(new ServletContextInitializer() { + + @Override + public void onStartup(ServletContext servletContext) throws ServletException { + servletContext.addFilter("faulty", new Filter() { + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + throw new ServletException("Faulty filter"); + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + chain.doFilter(request, response); + } + + @Override + public void destroy() { + } + + }); + } + + }); + this.thrown.expect(WebServerException.class); + factory.getWebServer().start(); + } + protected abstract void addConnector(int port, AbstractServletWebServerFactory factory);