diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/jetty/JettyAccessLogCustomizer.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/jetty/JettyAccessLogCustomizer.java index 6b04631c39..2799a3ed01 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/jetty/JettyAccessLogCustomizer.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/jetty/JettyAccessLogCustomizer.java @@ -25,8 +25,8 @@ import org.eclipse.jetty.server.Server; import org.springframework.boot.actuate.autoconfigure.web.server.AccessLogCustomizer; import org.springframework.boot.actuate.autoconfigure.web.server.ManagementServerProperties; -import org.springframework.boot.web.embedded.jetty.ConfigurableJettyWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.jetty.ConfigurableJettyWebServerFactory; import org.springframework.util.StringUtils; /** diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/reactive/ReactiveManagementContextAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/jetty/JettyReactiveManagementContextAutoConfiguration.java similarity index 60% rename from spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/reactive/ReactiveManagementContextAutoConfiguration.java rename to spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/jetty/JettyReactiveManagementContextAutoConfiguration.java index 5afb49200b..8a6b58b675 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/reactive/ReactiveManagementContextAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/jetty/JettyReactiveManagementContextAutoConfiguration.java @@ -14,39 +14,38 @@ * limitations under the License. */ -package org.springframework.boot.actuate.autoconfigure.web.reactive; +package org.springframework.boot.actuate.autoconfigure.web.server.jetty; -import reactor.core.publisher.Flux; +import org.eclipse.jetty.server.Server; import org.springframework.boot.WebApplicationType; import org.springframework.boot.actuate.autoconfigure.web.ManagementContextFactory; +import org.springframework.boot.actuate.autoconfigure.web.server.ConditionalOnManagementPort; +import org.springframework.boot.actuate.autoconfigure.web.server.ManagementPortType; import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; -import org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration; -import org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration; -import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; +import org.springframework.boot.autoconfigure.web.server.reactive.jetty.JettyReactiveWebServerAutoConfiguration; +import org.springframework.boot.web.server.reactive.ReactiveWebServerFactory; import org.springframework.context.annotation.Bean; /** - * {@link EnableAutoConfiguration Auto-configuration} for Reactive-specific management - * context concerns. + * Auto-configuration for a Jetty-based reactive management context. * - * @author Phillip Webb - * @since 2.0.0 + * @author Andy Wilkinson + * @since 4.0.0 */ @AutoConfiguration -@ConditionalOnClass(Flux.class) +@ConditionalOnClass(Server.class) @ConditionalOnWebApplication(type = Type.REACTIVE) -public class ReactiveManagementContextAutoConfiguration { +@ConditionalOnManagementPort(ManagementPortType.DIFFERENT) +public class JettyReactiveManagementContextAutoConfiguration { @Bean - public static ManagementContextFactory reactiveWebChildContextFactory() { + static ManagementContextFactory reactiveWebChildContextFactory() { return new ManagementContextFactory(WebApplicationType.REACTIVE, ReactiveWebServerFactory.class, - ReactiveWebServerFactoryAutoConfiguration.class, - EmbeddedWebServerFactoryCustomizerAutoConfiguration.class); + JettyReactiveWebServerAutoConfiguration.class); } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/jetty/JettyServletManagementContextAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/jetty/JettyServletManagementContextAutoConfiguration.java new file mode 100644 index 0000000000..b7b91f565f --- /dev/null +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/jetty/JettyServletManagementContextAutoConfiguration.java @@ -0,0 +1,51 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.actuate.autoconfigure.web.server.jetty; + +import org.eclipse.jetty.server.Server; + +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.actuate.autoconfigure.web.ManagementContextFactory; +import org.springframework.boot.actuate.autoconfigure.web.server.ConditionalOnManagementPort; +import org.springframework.boot.actuate.autoconfigure.web.server.ManagementPortType; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; +import org.springframework.boot.autoconfigure.web.server.servlet.jetty.JettyServletWebServerAutoConfiguration; +import org.springframework.boot.web.server.servlet.ServletWebServerFactory; +import org.springframework.context.annotation.Bean; + +/** + * Auto-configuration for a Jetty-based servlet management context. + * + * @author Andy Wilkinson + * @since 4.0.0 + */ +@AutoConfiguration +@ConditionalOnClass(Server.class) +@ConditionalOnWebApplication(type = Type.SERVLET) +@ConditionalOnManagementPort(ManagementPortType.DIFFERENT) +public class JettyServletManagementContextAutoConfiguration { + + @Bean + static ManagementContextFactory servletWebChildContextFactory() { + return new ManagementContextFactory(WebApplicationType.SERVLET, ServletWebServerFactory.class, + JettyServletWebServerAutoConfiguration.class); + } + +} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/netty/NettyReactiveManagementChildContextConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/netty/NettyReactiveManagementChildContextConfiguration.java new file mode 100644 index 0000000000..ad32898568 --- /dev/null +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/netty/NettyReactiveManagementChildContextConfiguration.java @@ -0,0 +1,53 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.actuate.autoconfigure.web.server.netty; + +import reactor.netty.http.server.HttpServer; + +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration; +import org.springframework.boot.actuate.autoconfigure.web.ManagementContextFactory; +import org.springframework.boot.actuate.autoconfigure.web.ManagementContextType; +import org.springframework.boot.actuate.autoconfigure.web.server.ManagementServerProperties; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; +import org.springframework.boot.autoconfigure.web.server.reactive.netty.NettyReactiveWebServerAutoConfiguration; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.web.server.reactive.ReactiveWebServerFactory; +import org.springframework.context.annotation.Bean; + +/** + * {@link ManagementContextConfiguration @ManagementContextConfiguration} for Netty-based + * reactive web endpoint infrastructure when a separate management context running on a + * different port is required. + * + * @author Andy Wilkinson + */ +@ConditionalOnClass(HttpServer.class) +@ConditionalOnWebApplication(type = Type.REACTIVE) +@EnableConfigurationProperties(ManagementServerProperties.class) +@ManagementContextConfiguration(value = ManagementContextType.CHILD, proxyBeanMethods = false) +class NettyReactiveManagementChildContextConfiguration { + + @Bean + static ManagementContextFactory reactiveWebChildContextFactory() { + return new ManagementContextFactory(WebApplicationType.REACTIVE, ReactiveWebServerFactory.class, + NettyReactiveWebServerAutoConfiguration.class); + } + +} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/netty/NettyReactiveManagementContextAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/netty/NettyReactiveManagementContextAutoConfiguration.java new file mode 100644 index 0000000000..25144fe665 --- /dev/null +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/netty/NettyReactiveManagementContextAutoConfiguration.java @@ -0,0 +1,51 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.actuate.autoconfigure.web.server.netty; + +import reactor.netty.http.server.HttpServer; + +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.actuate.autoconfigure.web.ManagementContextFactory; +import org.springframework.boot.actuate.autoconfigure.web.server.ConditionalOnManagementPort; +import org.springframework.boot.actuate.autoconfigure.web.server.ManagementPortType; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; +import org.springframework.boot.autoconfigure.web.server.reactive.netty.NettyReactiveWebServerAutoConfiguration; +import org.springframework.boot.web.server.reactive.ReactiveWebServerFactory; +import org.springframework.context.annotation.Bean; + +/** + * Auto-configuration for a Netty-based reactive management context. + * + * @author Andy Wilkinson + * @since 4.0.0 + */ +@AutoConfiguration +@ConditionalOnClass(HttpServer.class) +@ConditionalOnWebApplication(type = Type.REACTIVE) +@ConditionalOnManagementPort(ManagementPortType.DIFFERENT) +public class NettyReactiveManagementContextAutoConfiguration { + + @Bean + static ManagementContextFactory reactiveWebChildContextFactory() { + return new ManagementContextFactory(WebApplicationType.REACTIVE, ReactiveWebServerFactory.class, + NettyReactiveWebServerAutoConfiguration.class); + } + +} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/package-info.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/netty/package-info.java similarity index 85% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/package-info.java rename to spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/netty/package-info.java index 8a52c2e8b5..e7eb2ddbd0 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/package-info.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/netty/package-info.java @@ -15,6 +15,6 @@ */ /** - * Servlet web server abstractions. + * Actuator Netty web server support. */ -package org.springframework.boot.web.servlet.server; +package org.springframework.boot.actuate.autoconfigure.web.server.netty; diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/tomcat/TomcatAccessLogCustomizer.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/tomcat/TomcatAccessLogCustomizer.java index b4b75f9c68..5662a8ced1 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/tomcat/TomcatAccessLogCustomizer.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/tomcat/TomcatAccessLogCustomizer.java @@ -24,7 +24,7 @@ import org.apache.catalina.valves.AccessLogValve; import org.springframework.boot.actuate.autoconfigure.web.server.AccessLogCustomizer; import org.springframework.boot.actuate.autoconfigure.web.server.ManagementServerProperties; -import org.springframework.boot.web.embedded.tomcat.ConfigurableTomcatWebServerFactory; +import org.springframework.boot.web.server.tomcat.ConfigurableTomcatWebServerFactory; /** * {@link AccessLogCustomizer} for Tomcat. diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/tomcat/TomcatReactiveManagementChildContextConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/tomcat/TomcatReactiveManagementChildContextConfiguration.java index e39305fd4f..e7d2b7567b 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/tomcat/TomcatReactiveManagementChildContextConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/tomcat/TomcatReactiveManagementChildContextConfiguration.java @@ -25,7 +25,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.tomcat.TomcatReactiveWebServerFactory; import org.springframework.context.annotation.Bean; /** diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/tomcat/TomcatReactiveManagementContextAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/tomcat/TomcatReactiveManagementContextAutoConfiguration.java new file mode 100644 index 0000000000..9fc1e61a46 --- /dev/null +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/tomcat/TomcatReactiveManagementContextAutoConfiguration.java @@ -0,0 +1,52 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.actuate.autoconfigure.web.server.tomcat; + +import org.apache.catalina.startup.Tomcat; + +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.actuate.autoconfigure.web.ManagementContextFactory; +import org.springframework.boot.actuate.autoconfigure.web.server.ConditionalOnManagementPort; +import org.springframework.boot.actuate.autoconfigure.web.server.ManagementPortType; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; +import org.springframework.boot.autoconfigure.web.server.reactive.tomcat.TomcatReactiveWebServerAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.tomcat.TomcatWebServerConfiguration; +import org.springframework.boot.web.server.reactive.ReactiveWebServerFactory; +import org.springframework.context.annotation.Bean; + +/** + * Auto-configuration for a Tomcat-based reactive management context. + * + * @author Andy Wilkinson + * @since 4.0.0 + */ +@AutoConfiguration +@ConditionalOnClass(Tomcat.class) +@ConditionalOnWebApplication(type = Type.REACTIVE) +@ConditionalOnManagementPort(ManagementPortType.DIFFERENT) +public class TomcatReactiveManagementContextAutoConfiguration { + + @Bean + static ManagementContextFactory reactiveWebChildContextFactory() { + return new ManagementContextFactory(WebApplicationType.REACTIVE, ReactiveWebServerFactory.class, + TomcatReactiveWebServerAutoConfiguration.class, TomcatWebServerConfiguration.class); + } + +} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/tomcat/TomcatServletManagementChildContextConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/tomcat/TomcatServletManagementChildContextConfiguration.java index 6e790707d1..fe52bacf62 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/tomcat/TomcatServletManagementChildContextConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/tomcat/TomcatServletManagementChildContextConfiguration.java @@ -25,7 +25,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.context.annotation.Bean; /** diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/tomcat/TomcatServletManagementContextAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/tomcat/TomcatServletManagementContextAutoConfiguration.java new file mode 100644 index 0000000000..5f37a375f3 --- /dev/null +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/tomcat/TomcatServletManagementContextAutoConfiguration.java @@ -0,0 +1,52 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.actuate.autoconfigure.web.server.tomcat; + +import org.apache.catalina.startup.Tomcat; + +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.actuate.autoconfigure.web.ManagementContextFactory; +import org.springframework.boot.actuate.autoconfigure.web.server.ConditionalOnManagementPort; +import org.springframework.boot.actuate.autoconfigure.web.server.ManagementPortType; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.tomcat.TomcatWebServerConfiguration; +import org.springframework.boot.web.server.servlet.ServletWebServerFactory; +import org.springframework.context.annotation.Bean; + +/** + * Auto-configuration for a Tomcat-based servlet management context. + * + * @author Andy Wilkinson + * @since 4.0.0 + */ +@AutoConfiguration +@ConditionalOnClass(Tomcat.class) +@ConditionalOnWebApplication(type = Type.SERVLET) +@ConditionalOnManagementPort(ManagementPortType.DIFFERENT) +public class TomcatServletManagementContextAutoConfiguration { + + @Bean + static ManagementContextFactory servletWebChildContextFactory() { + return new ManagementContextFactory(WebApplicationType.SERVLET, ServletWebServerFactory.class, + TomcatWebServerConfiguration.class, TomcatServletWebServerAutoConfiguration.class); + } + +} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/undertow/UndertowAccessLogCustomizer.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/undertow/UndertowAccessLogCustomizer.java index fd7419654d..0f9e24be7a 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/undertow/UndertowAccessLogCustomizer.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/undertow/UndertowAccessLogCustomizer.java @@ -20,7 +20,7 @@ import java.util.function.Function; import org.springframework.boot.actuate.autoconfigure.web.server.AccessLogCustomizer; import org.springframework.boot.actuate.autoconfigure.web.server.ManagementServerProperties; -import org.springframework.boot.web.embedded.undertow.ConfigurableUndertowWebServerFactory; +import org.springframework.boot.web.server.undertow.ConfigurableUndertowWebServerFactory; /** * {@link AccessLogCustomizer} for Undertow. diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/undertow/UndertowReactiveManagementChildContextConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/undertow/UndertowReactiveManagementChildContextConfiguration.java index a7bc78a5b5..aed23a71ea 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/undertow/UndertowReactiveManagementChildContextConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/undertow/UndertowReactiveManagementChildContextConfiguration.java @@ -18,14 +18,18 @@ package org.springframework.boot.actuate.autoconfigure.web.server.undertow; import io.undertow.Undertow; +import org.springframework.boot.WebApplicationType; import org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration; +import org.springframework.boot.actuate.autoconfigure.web.ManagementContextFactory; import org.springframework.boot.actuate.autoconfigure.web.ManagementContextType; import org.springframework.boot.actuate.autoconfigure.web.server.ManagementServerProperties; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; +import org.springframework.boot.autoconfigure.web.server.reactive.undertow.UndertowReactiveWebServerAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.web.embedded.undertow.UndertowReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.ReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.undertow.UndertowReactiveWebServerFactory; import org.springframework.context.annotation.Bean; /** @@ -41,6 +45,12 @@ import org.springframework.context.annotation.Bean; @ManagementContextConfiguration(value = ManagementContextType.CHILD, proxyBeanMethods = false) class UndertowReactiveManagementChildContextConfiguration { + @Bean + static ManagementContextFactory reactiveWebChildContextFactory() { + return new ManagementContextFactory(WebApplicationType.REACTIVE, ReactiveWebServerFactory.class, + UndertowReactiveWebServerAutoConfiguration.class); + } + @Bean UndertowAccessLogCustomizer undertowManagementAccessLogCustomizer( ManagementServerProperties properties) { diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/undertow/UndertowReactiveManagementContextAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/undertow/UndertowReactiveManagementContextAutoConfiguration.java new file mode 100644 index 0000000000..c934266825 --- /dev/null +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/undertow/UndertowReactiveManagementContextAutoConfiguration.java @@ -0,0 +1,51 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.actuate.autoconfigure.web.server.undertow; + +import io.undertow.Undertow; + +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.actuate.autoconfigure.web.ManagementContextFactory; +import org.springframework.boot.actuate.autoconfigure.web.server.ConditionalOnManagementPort; +import org.springframework.boot.actuate.autoconfigure.web.server.ManagementPortType; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; +import org.springframework.boot.autoconfigure.web.server.reactive.undertow.UndertowReactiveWebServerAutoConfiguration; +import org.springframework.boot.web.server.reactive.ReactiveWebServerFactory; +import org.springframework.context.annotation.Bean; + +/** + * Auto-configuration for an Undertow-based reactive management context. + * + * @author Andy Wilkinson + * @since 4.0.0 + */ +@AutoConfiguration +@ConditionalOnClass(Undertow.class) +@ConditionalOnWebApplication(type = Type.REACTIVE) +@ConditionalOnManagementPort(ManagementPortType.DIFFERENT) +public class UndertowReactiveManagementContextAutoConfiguration { + + @Bean + static ManagementContextFactory reactiveWebChildContextFactory() { + return new ManagementContextFactory(WebApplicationType.REACTIVE, ReactiveWebServerFactory.class, + UndertowReactiveWebServerAutoConfiguration.class); + } + +} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/undertow/UndertowServletManagementChildContextConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/undertow/UndertowServletManagementChildContextConfiguration.java index 8d69cedf92..65699855b7 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/undertow/UndertowServletManagementChildContextConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/undertow/UndertowServletManagementChildContextConfiguration.java @@ -25,7 +25,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory; +import org.springframework.boot.web.server.servlet.undertow.UndertowServletWebServerFactory; import org.springframework.context.annotation.Bean; /** diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/undertow/UndertowServletManagementContextAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/undertow/UndertowServletManagementContextAutoConfiguration.java new file mode 100644 index 0000000000..46ded30f64 --- /dev/null +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/undertow/UndertowServletManagementContextAutoConfiguration.java @@ -0,0 +1,51 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.actuate.autoconfigure.web.server.undertow; + +import io.undertow.Undertow; + +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.actuate.autoconfigure.web.ManagementContextFactory; +import org.springframework.boot.actuate.autoconfigure.web.server.ConditionalOnManagementPort; +import org.springframework.boot.actuate.autoconfigure.web.server.ManagementPortType; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; +import org.springframework.boot.autoconfigure.web.server.servlet.undertow.UndertowServletWebServerAutoConfiguration; +import org.springframework.boot.web.server.servlet.ServletWebServerFactory; +import org.springframework.context.annotation.Bean; + +/** + * Auto-configuration for an Undertow-based servlet management context. + * + * @author Andy Wilkinson + * @since 4.0.0 + */ +@AutoConfiguration +@ConditionalOnClass(Undertow.class) +@ConditionalOnWebApplication(type = Type.SERVLET) +@ConditionalOnManagementPort(ManagementPortType.DIFFERENT) +public class UndertowServletManagementContextAutoConfiguration { + + @Bean + static ManagementContextFactory servletWebChildContextFactory() { + return new ManagementContextFactory(WebApplicationType.SERVLET, ServletWebServerFactory.class, + UndertowServletWebServerAutoConfiguration.class); + } + +} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/servlet/ServletManagementContextAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/servlet/ServletManagementContextAutoConfiguration.java index 854ecc26b7..eab969aa26 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/servlet/ServletManagementContextAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/servlet/ServletManagementContextAutoConfiguration.java @@ -18,19 +18,14 @@ package org.springframework.boot.actuate.autoconfigure.web.servlet; import jakarta.servlet.Servlet; -import org.springframework.boot.WebApplicationType; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties; -import org.springframework.boot.actuate.autoconfigure.web.ManagementContextFactory; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; -import org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; import org.springframework.boot.web.servlet.filter.ApplicationContextHeaderFilter; -import org.springframework.boot.web.servlet.server.ServletWebServerFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -47,13 +42,6 @@ import org.springframework.context.annotation.Configuration; @ConditionalOnWebApplication(type = Type.SERVLET) public class ServletManagementContextAutoConfiguration { - @Bean - public static ManagementContextFactory servletWebChildContextFactory() { - return new ManagementContextFactory(WebApplicationType.SERVLET, ServletWebServerFactory.class, - ServletWebServerFactoryAutoConfiguration.class, - EmbeddedWebServerFactoryCustomizerAutoConfiguration.class); - } - @Bean public ManagementServletContext managementServletContext(WebEndpointProperties properties) { return properties::getBasePath; diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/servlet/ServletManagementWebServerFactoryCustomizer.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/servlet/ServletManagementWebServerFactoryCustomizer.java index 3e8ac7a2b4..e4f136df53 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/servlet/ServletManagementWebServerFactoryCustomizer.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/servlet/ServletManagementWebServerFactoryCustomizer.java @@ -20,7 +20,7 @@ import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.boot.actuate.autoconfigure.web.server.ManagementServerProperties; import org.springframework.boot.actuate.autoconfigure.web.server.ManagementWebServerFactoryCustomizer; import org.springframework.boot.autoconfigure.web.ServerProperties; -import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; +import org.springframework.boot.web.server.servlet.ConfigurableServletWebServerFactory; import org.springframework.util.StringUtils; /** diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/servlet/WebMvcEndpointChildContextConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/servlet/WebMvcEndpointChildContextConfiguration.java index 45ec3ac3d4..e95ad224e5 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/servlet/WebMvcEndpointChildContextConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/servlet/WebMvcEndpointChildContextConfiguration.java @@ -29,9 +29,9 @@ import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoC import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletRegistrationBean; import org.springframework.boot.web.server.ErrorPage; import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.servlet.ConfigurableServletWebServerFactory; import org.springframework.boot.web.servlet.error.ErrorAttributes; import org.springframework.boot.web.servlet.filter.OrderedRequestContextFilter; -import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.core.Ordered; import org.springframework.web.context.request.RequestContextListener; diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index ff22848cf1..5057d18d42 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -87,8 +87,6 @@ org.springframework.boot.actuate.autoconfigure.metrics.web.tomcat.TomcatMetricsA org.springframework.boot.actuate.autoconfigure.neo4j.Neo4jHealthContributorAutoConfiguration org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration org.springframework.boot.actuate.autoconfigure.observation.batch.BatchObservationAutoConfiguration -org.springframework.boot.actuate.autoconfigure.observation.batch.BatchObservationAutoConfiguration -org.springframework.boot.actuate.autoconfigure.observation.graphql.GraphQlObservationAutoConfiguration org.springframework.boot.actuate.autoconfigure.observation.graphql.GraphQlObservationAutoConfiguration org.springframework.boot.actuate.autoconfigure.observation.web.client.HttpClientObservationsAutoConfiguration org.springframework.boot.actuate.autoconfigure.observation.web.reactive.WebFluxObservationAutoConfiguration @@ -117,6 +115,12 @@ org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinAutoConfigur org.springframework.boot.actuate.autoconfigure.web.exchanges.HttpExchangesAutoConfiguration org.springframework.boot.actuate.autoconfigure.web.exchanges.HttpExchangesEndpointAutoConfiguration org.springframework.boot.actuate.autoconfigure.web.mappings.MappingsEndpointAutoConfiguration -org.springframework.boot.actuate.autoconfigure.web.reactive.ReactiveManagementContextAutoConfiguration org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration +org.springframework.boot.actuate.autoconfigure.web.server.jetty.JettyReactiveManagementContextAutoConfiguration +org.springframework.boot.actuate.autoconfigure.web.server.jetty.JettyServletManagementContextAutoConfiguration +org.springframework.boot.actuate.autoconfigure.web.server.netty.NettyReactiveManagementContextAutoConfiguration +org.springframework.boot.actuate.autoconfigure.web.server.tomcat.TomcatReactiveManagementContextAutoConfiguration +org.springframework.boot.actuate.autoconfigure.web.server.tomcat.TomcatServletManagementContextAutoConfiguration +org.springframework.boot.actuate.autoconfigure.web.server.undertow.UndertowReactiveManagementContextAutoConfiguration +org.springframework.boot.actuate.autoconfigure.web.server.undertow.UndertowServletManagementContextAutoConfiguration org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/reactive/CloudFoundryWebFluxEndpointIntegrationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/reactive/CloudFoundryWebFluxEndpointIntegrationTests.java index 33d06aa6f7..9947dddddd 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/reactive/CloudFoundryWebFluxEndpointIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/reactive/CloudFoundryWebFluxEndpointIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -45,8 +45,8 @@ import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint; import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration; -import org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration; import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.reactive.netty.NettyReactiveWebServerAutoConfiguration; import org.springframework.boot.test.context.assertj.AssertableReactiveWebApplicationContext; import org.springframework.boot.test.context.runner.ContextConsumer; import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; @@ -82,7 +82,7 @@ class CloudFoundryWebFluxEndpointIntegrationTests { private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner( AnnotationConfigReactiveWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, HttpHandlerAutoConfiguration.class, - ReactiveWebServerFactoryAutoConfiguration.class)) + NettyReactiveWebServerAutoConfiguration.class)) .withUserConfiguration(TestEndpointConfiguration.class) .withBean(ReactiveTokenValidator.class, () -> this.tokenValidator) .withBean(ReactiveCloudFoundrySecurityService.class, () -> this.securityService) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/CloudFoundryMvcWebEndpointIntegrationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/CloudFoundryMvcWebEndpointIntegrationTests.java index 81440fd0b6..5e25ad9be1 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/CloudFoundryMvcWebEndpointIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/CloudFoundryMvcWebEndpointIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,7 +44,7 @@ import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes; import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint; import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/SkipSslVerificationHttpRequestFactoryTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/SkipSslVerificationHttpRequestFactoryTests.java index edaca1f623..fa1de4e291 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/SkipSslVerificationHttpRequestFactoryTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/SkipSslVerificationHttpRequestFactoryTests.java @@ -23,9 +23,9 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.testsupport.classpath.resources.WithPackageResources; import org.springframework.boot.testsupport.web.servlet.ExampleServlet; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.Ssl; import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/jersey/JerseyWebEndpointIntegrationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/jersey/JerseyWebEndpointIntegrationTests.java index b7bdb93c7e..fcde7dbfb4 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/jersey/JerseyWebEndpointIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/jersey/JerseyWebEndpointIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,7 +27,7 @@ import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAu import org.springframework.boot.actuate.autoconfigure.web.jersey.JerseySameManagementContextConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; @@ -49,7 +49,7 @@ class JerseyWebEndpointIntegrationTests { new WebApplicationContextRunner(AnnotationConfigServletWebServerApplicationContext::new) .withConfiguration( AutoConfigurations.of(JerseySameManagementContextConfiguration.class, JerseyAutoConfiguration.class, - ServletWebServerFactoryAutoConfiguration.class, EndpointAutoConfiguration.class, + TomcatServletWebServerAutoConfiguration.class, EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class, JerseyWebEndpointManagementContextConfiguration.class)) .withUserConfiguration(ResourceConfigConfiguration.class) .withClassLoader(new FilteredClassLoader(DispatcherServlet.class)) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/ControllerEndpointWebFluxIntegrationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/ControllerEndpointWebFluxIntegrationTests.java index eb322c827b..b364e922ab 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/ControllerEndpointWebFluxIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/ControllerEndpointWebFluxIntegrationTests.java @@ -23,7 +23,6 @@ import org.springframework.boot.actuate.autoconfigure.audit.AuditAutoConfigurati import org.springframework.boot.actuate.autoconfigure.beans.BeansEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.web.reactive.ReactiveManagementContextAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration; import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpoint; import org.springframework.boot.actuate.endpoint.web.annotation.RestControllerEndpoint; @@ -69,8 +68,7 @@ class ControllerEndpointWebFluxIntegrationTests { } @ImportAutoConfiguration({ JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, - EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class, - ReactiveManagementContextAutoConfiguration.class, AuditAutoConfiguration.class, + EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class, AuditAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class, WebFluxAutoConfiguration.class, ManagementContextAutoConfiguration.class, BeansEndpointAutoConfiguration.class }) static class DefaultConfiguration { diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/JerseyEndpointAccessIntegrationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/JerseyEndpointAccessIntegrationTests.java index 79491a3932..4192168b73 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/JerseyEndpointAccessIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/JerseyEndpointAccessIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,7 +33,7 @@ import org.springframework.boot.actuate.autoconfigure.web.server.ManagementConte import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; import org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; @@ -58,7 +58,7 @@ class JerseyEndpointAccessIntegrationTests { private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner( AnnotationConfigServletWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(JacksonAutoConfiguration.class, JerseyAutoConfiguration.class, - EndpointAutoConfiguration.class, ServletWebServerFactoryAutoConfiguration.class, + EndpointAutoConfiguration.class, TomcatServletWebServerAutoConfiguration.class, WebEndpointAutoConfiguration.class, ManagementContextAutoConfiguration.class, BeansEndpointAutoConfiguration.class)) .withClassLoader(new FilteredClassLoader(DispatcherServlet.class)) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/JerseyEndpointIntegrationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/JerseyEndpointIntegrationTests.java index 5a3a196441..2250ae62bc 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/JerseyEndpointIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/JerseyEndpointIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,7 +34,7 @@ import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; import org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration; import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; @@ -152,7 +152,7 @@ class JerseyEndpointIntegrationTests { private Class[] getAutoconfigurations(Class... additional) { List> autoconfigurations = new ArrayList<>(Arrays.asList(JacksonAutoConfiguration.class, JerseyAutoConfiguration.class, EndpointAutoConfiguration.class, - ServletWebServerFactoryAutoConfiguration.class, WebEndpointAutoConfiguration.class, + TomcatServletWebServerAutoConfiguration.class, WebEndpointAutoConfiguration.class, ManagementContextAutoConfiguration.class, BeansEndpointAutoConfiguration.class)); autoconfigurations.addAll(Arrays.asList(additional)); return autoconfigurations.toArray(new Class[0]); diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/JerseyHealthEndpointAdditionalPathIntegrationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/JerseyHealthEndpointAdditionalPathIntegrationTests.java index e995ddfd0e..61ff94a272 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/JerseyHealthEndpointAdditionalPathIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/JerseyHealthEndpointAdditionalPathIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,11 +21,12 @@ import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAu import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.system.DiskSpaceHealthContributorAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.web.server.tomcat.TomcatServletManagementContextAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; import org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; @@ -45,10 +46,11 @@ class JerseyHealthEndpointAdditionalPathIntegrationTests extends JerseyHealthEndpointAdditionalPathIntegrationTests() { super(new WebApplicationContextRunner(AnnotationConfigServletWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(JacksonAutoConfiguration.class, JerseyAutoConfiguration.class, - EndpointAutoConfiguration.class, ServletWebServerFactoryAutoConfiguration.class, - WebEndpointAutoConfiguration.class, JerseyAutoConfiguration.class, - ManagementContextAutoConfiguration.class, ServletManagementContextAutoConfiguration.class, - HealthEndpointAutoConfiguration.class, DiskSpaceHealthContributorAutoConfiguration.class)) + EndpointAutoConfiguration.class, TomcatServletWebServerAutoConfiguration.class, + TomcatServletManagementContextAutoConfiguration.class, WebEndpointAutoConfiguration.class, + JerseyAutoConfiguration.class, ManagementContextAutoConfiguration.class, + ServletManagementContextAutoConfiguration.class, HealthEndpointAutoConfiguration.class, + DiskSpaceHealthContributorAutoConfiguration.class)) .withInitializer(new ServerPortInfoApplicationContextInitializer()) .withClassLoader(new FilteredClassLoader(DispatcherServlet.class)) .withPropertyValues("server.port=0")); diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebFluxEndpointAccessIntegrationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebFluxEndpointAccessIntegrationTests.java index 341cd7c519..2b96964451 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebFluxEndpointAccessIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebFluxEndpointAccessIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,14 +22,13 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.web.reactive.ReactiveManagementContextAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; import org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration; -import org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration; import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.reactive.netty.NettyReactiveWebServerAutoConfiguration; import org.springframework.boot.test.context.assertj.AssertableReactiveWebApplicationContext; import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext; @@ -53,10 +52,10 @@ class WebFluxEndpointAccessIntegrationTests { private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner( AnnotationConfigReactiveWebServerApplicationContext::new) - .withConfiguration(AutoConfigurations.of(ReactiveWebServerFactoryAutoConfiguration.class, + .withConfiguration(AutoConfigurations.of(NettyReactiveWebServerAutoConfiguration.class, HttpHandlerAutoConfiguration.class, JacksonAutoConfiguration.class, CodecsAutoConfiguration.class, WebFluxAutoConfiguration.class, EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class, - ManagementContextAutoConfiguration.class, ReactiveManagementContextAutoConfiguration.class)) + ManagementContextAutoConfiguration.class)) .withConfiguration(AutoConfigurations.of(EndpointAutoConfigurationClasses.ALL)) .withUserConfiguration(CustomWebFluxEndpoint.class) .withPropertyValues("server.port:0"); diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebFluxEndpointCorsIntegrationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebFluxEndpointCorsIntegrationTests.java index c04d88d360..c948f1c436 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebFluxEndpointCorsIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebFluxEndpointCorsIntegrationTests.java @@ -24,7 +24,6 @@ import org.springframework.boot.actuate.autoconfigure.beans.BeansEndpointAutoCon import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.web.reactive.WebFluxEndpointManagementContextConfiguration; -import org.springframework.boot.actuate.autoconfigure.web.reactive.ReactiveManagementContextAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration; @@ -50,7 +49,7 @@ class WebFluxEndpointCorsIntegrationTests { .withConfiguration(AutoConfigurations.of(JacksonAutoConfiguration.class, CodecsAutoConfiguration.class, WebFluxAutoConfiguration.class, HttpHandlerAutoConfiguration.class, EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class, ManagementContextAutoConfiguration.class, - ReactiveManagementContextAutoConfiguration.class, BeansEndpointAutoConfiguration.class)) + BeansEndpointAutoConfiguration.class)) .withPropertyValues("management.endpoints.web.exposure.include:*"); @Test diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebFluxEndpointIntegrationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebFluxEndpointIntegrationTests.java index ab3fc50a85..7f832d536e 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebFluxEndpointIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebFluxEndpointIntegrationTests.java @@ -23,7 +23,6 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.actuate.autoconfigure.beans.BeansEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.web.reactive.ReactiveManagementContextAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration; @@ -49,7 +48,7 @@ class WebFluxEndpointIntegrationTests { .withConfiguration(AutoConfigurations.of(JacksonAutoConfiguration.class, CodecsAutoConfiguration.class, WebFluxAutoConfiguration.class, HttpHandlerAutoConfiguration.class, EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class, ManagementContextAutoConfiguration.class, - ReactiveManagementContextAutoConfiguration.class, BeansEndpointAutoConfiguration.class)) + BeansEndpointAutoConfiguration.class)) .withUserConfiguration(EndpointsConfiguration.class); @Test diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebFluxHealthEndpointAdditionalPathIntegrationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebFluxHealthEndpointAdditionalPathIntegrationTests.java index 2010657947..d65c3721bd 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebFluxHealthEndpointAdditionalPathIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebFluxHealthEndpointAdditionalPathIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,14 +21,14 @@ import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfi import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.system.DiskSpaceHealthContributorAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.web.reactive.ReactiveManagementContextAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.web.server.netty.NettyReactiveManagementContextAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; import org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration; -import org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration; import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.reactive.netty.NettyReactiveWebServerAutoConfiguration; import org.springframework.boot.test.context.assertj.AssertableReactiveWebApplicationContext; import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; import org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer; @@ -49,8 +49,8 @@ class WebFluxHealthEndpointAdditionalPathIntegrationTests extends WebFluxAutoConfiguration.class, HttpHandlerAutoConfiguration.class, EndpointAutoConfiguration.class, HealthEndpointAutoConfiguration.class, DiskSpaceHealthContributorAutoConfiguration.class, WebEndpointAutoConfiguration.class, ManagementContextAutoConfiguration.class, - ReactiveWebServerFactoryAutoConfiguration.class, ReactiveManagementContextAutoConfiguration.class, - BeansEndpointAutoConfiguration.class)) + NettyReactiveWebServerAutoConfiguration.class, + NettyReactiveManagementContextAutoConfiguration.class, BeansEndpointAutoConfiguration.class)) .withInitializer(new ServerPortInfoApplicationContextInitializer()) .withPropertyValues("server.port=0")); } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebMvcEndpointAccessIntegrationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebMvcEndpointAccessIntegrationTests.java index b574f05fc2..89c3433ffb 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebMvcEndpointAccessIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebMvcEndpointAccessIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,8 +34,8 @@ import org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagem import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; @@ -60,10 +60,10 @@ class WebMvcEndpointAccessIntegrationTests { private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner( AnnotationConfigServletWebServerApplicationContext::new) - .withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class, - DispatcherServletAutoConfiguration.class, JacksonAutoConfiguration.class, - HttpMessageConvertersAutoConfiguration.class, WebMvcAutoConfiguration.class, - EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class, + .withConfiguration(AutoConfigurations.of(TomcatServletWebServerAutoConfiguration.class, + TomcatServletWebServerAutoConfiguration.class, DispatcherServletAutoConfiguration.class, + JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, + WebMvcAutoConfiguration.class, EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class, ManagementContextAutoConfiguration.class, ServletManagementContextAutoConfiguration.class, HealthContributorAutoConfiguration.class)) .withConfiguration(AutoConfigurations.of(EndpointAutoConfigurationClasses.ALL)) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebMvcEndpointExposureIntegrationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebMvcEndpointExposureIntegrationTests.java index 553a5ad92c..c813de98b7 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebMvcEndpointExposureIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebMvcEndpointExposureIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,8 +37,8 @@ import org.springframework.boot.actuate.web.exchanges.InMemoryHttpExchangeReposi import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; @@ -65,13 +65,13 @@ class WebMvcEndpointExposureIntegrationTests { private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner( AnnotationConfigServletWebServerApplicationContext::new) - .withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class, - DispatcherServletAutoConfiguration.class, JacksonAutoConfiguration.class, - HttpMessageConvertersAutoConfiguration.class, WebMvcAutoConfiguration.class, - EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class, - ManagementContextAutoConfiguration.class, ServletManagementContextAutoConfiguration.class, - ManagementContextAutoConfiguration.class, ServletManagementContextAutoConfiguration.class, - HttpExchangesAutoConfiguration.class, HealthContributorAutoConfiguration.class)) + .withConfiguration(AutoConfigurations.of(TomcatServletWebServerAutoConfiguration.class, + TomcatServletWebServerAutoConfiguration.class, DispatcherServletAutoConfiguration.class, + JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, + WebMvcAutoConfiguration.class, EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class, + ManagementContextAutoConfiguration.class, ManagementContextAutoConfiguration.class, + ServletManagementContextAutoConfiguration.class, HttpExchangesAutoConfiguration.class, + HealthContributorAutoConfiguration.class)) .withConfiguration(AutoConfigurations.of(EndpointAutoConfigurationClasses.ALL)) .withUserConfiguration(CustomMvcEndpoint.class, CustomServletEndpoint.class, HttpExchangeRepositoryConfiguration.class, AuditEventRepositoryConfiguration.class) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebMvcHealthEndpointAdditionalPathIntegrationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebMvcHealthEndpointAdditionalPathIntegrationTests.java index 1c2167bdbb..492a84878e 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebMvcHealthEndpointAdditionalPathIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebMvcHealthEndpointAdditionalPathIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,12 +21,13 @@ import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAu import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.system.DiskSpaceHealthContributorAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.web.server.tomcat.TomcatServletManagementContextAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; @@ -46,7 +47,8 @@ class WebMvcHealthEndpointAdditionalPathIntegrationTests extends super(new WebApplicationContextRunner(AnnotationConfigServletWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, ManagementContextAutoConfiguration.class, - ServletWebServerFactoryAutoConfiguration.class, WebMvcAutoConfiguration.class, + TomcatServletWebServerAutoConfiguration.class, TomcatServletWebServerAutoConfiguration.class, + TomcatServletManagementContextAutoConfiguration.class, WebMvcAutoConfiguration.class, ServletManagementContextAutoConfiguration.class, WebEndpointAutoConfiguration.class, EndpointAutoConfiguration.class, DispatcherServletAutoConfiguration.class, HealthEndpointAutoConfiguration.class, DiskSpaceHealthContributorAutoConfiguration.class)) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey/JerseyServerMetricsAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey/JerseyServerMetricsAutoConfigurationTests.java index aea79842ce..16db41b101 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey/JerseyServerMetricsAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey/JerseyServerMetricsAutoConfigurationTests.java @@ -34,7 +34,7 @@ import org.springframework.boot.actuate.autoconfigure.observation.ObservationAut import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration; import org.springframework.boot.autoconfigure.jersey.ResourceConfigCustomizer; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -60,10 +60,10 @@ class JerseyServerMetricsAutoConfigurationTests { private final WebApplicationContextRunner webContextRunner = new WebApplicationContextRunner( AnnotationConfigServletWebServerApplicationContext::new) - .withConfiguration( - AutoConfigurations.of(JerseyAutoConfiguration.class, JerseyServerMetricsAutoConfiguration.class, - ServletWebServerFactoryAutoConfiguration.class, SimpleMetricsExportAutoConfiguration.class, - ObservationAutoConfiguration.class, MetricsAutoConfiguration.class)) + .withConfiguration(AutoConfigurations.of(JerseyAutoConfiguration.class, + JerseyServerMetricsAutoConfiguration.class, TomcatServletWebServerAutoConfiguration.class, + TomcatServletWebServerAutoConfiguration.class, SimpleMetricsExportAutoConfiguration.class, + ObservationAutoConfiguration.class, MetricsAutoConfiguration.class)) .withUserConfiguration(ResourceConfiguration.class) .withPropertyValues("server.port:0"); diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/test/MetricsIntegrationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/test/MetricsIntegrationTests.java index dfccd085e8..bc6cc61b00 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/test/MetricsIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/test/MetricsIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -50,8 +50,8 @@ import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; @@ -152,7 +152,8 @@ class MetricsIntegrationTests { WebFluxObservationAutoConfiguration.class, WebMvcObservationAutoConfiguration.class, JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, RestTemplateAutoConfiguration.class, WebMvcAutoConfiguration.class, - DispatcherServletAutoConfiguration.class, ServletWebServerFactoryAutoConfiguration.class }) + DispatcherServletAutoConfiguration.class, TomcatServletWebServerAutoConfiguration.class, + TomcatServletWebServerAutoConfiguration.class }) @Import(PersonController.class) static class MetricsApp { diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/web/jetty/JettyMetricsAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/web/jetty/JettyMetricsAutoConfigurationTests.java index 23adfa9fa0..64d3fa7961 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/web/jetty/JettyMetricsAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/web/jetty/JettyMetricsAutoConfigurationTests.java @@ -26,15 +26,15 @@ import org.springframework.boot.actuate.metrics.web.jetty.JettyConnectionMetrics import org.springframework.boot.actuate.metrics.web.jetty.JettyServerThreadPoolMetricsBinder; import org.springframework.boot.actuate.metrics.web.jetty.JettySslHandshakeMetricsBinder; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.reactive.jetty.JettyReactiveWebServerAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.jetty.JettyServletWebServerAutoConfiguration; import org.springframework.boot.context.event.ApplicationStartedEvent; import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.boot.testsupport.classpath.resources.WithPackageResources; -import org.springframework.boot.web.embedded.jetty.JettyReactiveWebServerFactory; -import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory; import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext; +import org.springframework.boot.web.server.reactive.jetty.JettyReactiveWebServerFactory; +import org.springframework.boot.web.server.servlet.jetty.JettyServletWebServerFactory; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; @@ -56,7 +56,7 @@ class JettyMetricsAutoConfigurationTests { void autoConfiguresThreadPoolMetricsWithEmbeddedServletJetty() { new WebApplicationContextRunner(AnnotationConfigServletWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(JettyMetricsAutoConfiguration.class, - ServletWebServerFactoryAutoConfiguration.class)) + JettyServletWebServerAutoConfiguration.class)) .withUserConfiguration(ServletWebServerConfiguration.class, MeterRegistryConfiguration.class) .run((context) -> { context.publishEvent(createApplicationStartedEvent(context.getSourceApplicationContext())); @@ -70,7 +70,7 @@ class JettyMetricsAutoConfigurationTests { void autoConfiguresThreadPoolMetricsWithEmbeddedReactiveJetty() { new ReactiveWebApplicationContextRunner(AnnotationConfigReactiveWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(JettyMetricsAutoConfiguration.class, - ReactiveWebServerFactoryAutoConfiguration.class)) + JettyReactiveWebServerAutoConfiguration.class)) .withUserConfiguration(ReactiveWebServerConfiguration.class, MeterRegistryConfiguration.class) .run((context) -> { context.publishEvent(createApplicationStartedEvent(context.getSourceApplicationContext())); @@ -91,7 +91,7 @@ class JettyMetricsAutoConfigurationTests { void autoConfiguresConnectionMetricsWithEmbeddedServletJetty() { new WebApplicationContextRunner(AnnotationConfigServletWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(JettyMetricsAutoConfiguration.class, - ServletWebServerFactoryAutoConfiguration.class)) + JettyServletWebServerAutoConfiguration.class)) .withUserConfiguration(ServletWebServerConfiguration.class, MeterRegistryConfiguration.class) .run((context) -> { context.publishEvent(createApplicationStartedEvent(context.getSourceApplicationContext())); @@ -105,7 +105,7 @@ class JettyMetricsAutoConfigurationTests { void autoConfiguresConnectionMetricsWithEmbeddedReactiveJetty() { new ReactiveWebApplicationContextRunner(AnnotationConfigReactiveWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(JettyMetricsAutoConfiguration.class, - ReactiveWebServerFactoryAutoConfiguration.class)) + JettyReactiveWebServerAutoConfiguration.class)) .withUserConfiguration(ReactiveWebServerConfiguration.class, MeterRegistryConfiguration.class) .run((context) -> { context.publishEvent(createApplicationStartedEvent(context.getSourceApplicationContext())); @@ -118,7 +118,7 @@ class JettyMetricsAutoConfigurationTests { void allowsCustomJettyConnectionMetricsBinderToBeUsed() { new WebApplicationContextRunner(AnnotationConfigServletWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(JettyMetricsAutoConfiguration.class, - ServletWebServerFactoryAutoConfiguration.class)) + JettyServletWebServerAutoConfiguration.class)) .withUserConfiguration(ServletWebServerConfiguration.class, CustomJettyConnectionMetricsBinder.class, MeterRegistryConfiguration.class) .run((context) -> { @@ -137,7 +137,7 @@ class JettyMetricsAutoConfigurationTests { void autoConfiguresSslHandshakeMetricsWithEmbeddedServletJetty() { new WebApplicationContextRunner(AnnotationConfigServletWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(JettyMetricsAutoConfiguration.class, - ServletWebServerFactoryAutoConfiguration.class)) + JettyServletWebServerAutoConfiguration.class)) .withUserConfiguration(ServletWebServerConfiguration.class, MeterRegistryConfiguration.class) .withPropertyValues("server.ssl.enabled=true", "server.ssl.key-store=classpath:test.jks", "server.ssl.key-store-password=secret", "server.ssl.key-password=password") @@ -154,7 +154,7 @@ class JettyMetricsAutoConfigurationTests { void autoConfiguresSslHandshakeMetricsWithEmbeddedReactiveJetty() { new ReactiveWebApplicationContextRunner(AnnotationConfigReactiveWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(JettyMetricsAutoConfiguration.class, - ReactiveWebServerFactoryAutoConfiguration.class)) + JettyReactiveWebServerAutoConfiguration.class)) .withUserConfiguration(ReactiveWebServerConfiguration.class, MeterRegistryConfiguration.class) .withPropertyValues("server.ssl.enabled=true", "server.ssl.key-store=classpath:test.jks", "server.ssl.key-store-password=secret", "server.ssl.key-password=password") @@ -170,7 +170,7 @@ class JettyMetricsAutoConfigurationTests { void allowsCustomJettySslHandshakeMetricsBinderToBeUsed() { new WebApplicationContextRunner(AnnotationConfigServletWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(JettyMetricsAutoConfiguration.class, - ServletWebServerFactoryAutoConfiguration.class)) + JettyServletWebServerAutoConfiguration.class)) .withUserConfiguration(ServletWebServerConfiguration.class, CustomJettySslHandshakeMetricsBinder.class, MeterRegistryConfiguration.class) .withPropertyValues("server.ssl.enabled=true", "server.ssl.key-store=classpath:test.jks", @@ -196,7 +196,7 @@ class JettyMetricsAutoConfigurationTests { void doesNotAutoConfigureSslHandshakeMetricsWhenSslEnabledPropertyNotSpecified() { new WebApplicationContextRunner(AnnotationConfigServletWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(JettyMetricsAutoConfiguration.class, - ServletWebServerFactoryAutoConfiguration.class)) + JettyServletWebServerAutoConfiguration.class)) .withUserConfiguration(ServletWebServerConfiguration.class, MeterRegistryConfiguration.class) .run((context) -> assertThat(context).doesNotHaveBean(JettySslHandshakeMetricsBinder.class)); } @@ -205,7 +205,7 @@ class JettyMetricsAutoConfigurationTests { void doesNotAutoConfigureSslHandshakeMetricsWhenSslEnabledPropertySetToFalse() { new WebApplicationContextRunner(AnnotationConfigServletWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(JettyMetricsAutoConfiguration.class, - ServletWebServerFactoryAutoConfiguration.class)) + JettyServletWebServerAutoConfiguration.class)) .withUserConfiguration(ServletWebServerConfiguration.class, MeterRegistryConfiguration.class) .withPropertyValues("server.ssl.enabled: false") .run((context) -> assertThat(context).doesNotHaveBean(JettySslHandshakeMetricsBinder.class)); diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/web/tomcat/TomcatMetricsAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/web/tomcat/TomcatMetricsAutoConfigurationTests.java index 0fe2d3c39e..b9b7e39333 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/web/tomcat/TomcatMetricsAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/web/tomcat/TomcatMetricsAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,15 +28,15 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.SpringApplication; import org.springframework.boot.actuate.metrics.web.tomcat.TomcatMetricsBinder; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.reactive.tomcat.TomcatReactiveWebServerAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.context.event.ApplicationStartedEvent; import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; -import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; -import org.springframework.boot.web.embedded.tomcat.TomcatWebServer; import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext; +import org.springframework.boot.web.server.reactive.tomcat.TomcatReactiveWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.tomcat.TomcatWebServer; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; @@ -59,7 +59,7 @@ class TomcatMetricsAutoConfigurationTests { resetTomcatState(); new WebApplicationContextRunner(AnnotationConfigServletWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(TomcatMetricsAutoConfiguration.class, - ServletWebServerFactoryAutoConfiguration.class)) + TomcatServletWebServerAutoConfiguration.class)) .withUserConfiguration(ServletWebServerConfiguration.class, MeterRegistryConfiguration.class) .withPropertyValues("server.tomcat.mbeanregistry.enabled=true") .run((context) -> { @@ -76,7 +76,7 @@ class TomcatMetricsAutoConfigurationTests { resetTomcatState(); new ReactiveWebApplicationContextRunner(AnnotationConfigReactiveWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(TomcatMetricsAutoConfiguration.class, - ReactiveWebServerFactoryAutoConfiguration.class)) + TomcatReactiveWebServerAutoConfiguration.class)) .withUserConfiguration(ReactiveWebServerConfiguration.class, MeterRegistryConfiguration.class) .withPropertyValues("server.tomcat.mbeanregistry.enabled=true") .run((context) -> { diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/reactive/EndpointRequestIntegrationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/reactive/EndpointRequestIntegrationTests.java index d127ab0685..ad8db16605 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/reactive/EndpointRequestIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/reactive/EndpointRequestIntegrationTests.java @@ -38,8 +38,8 @@ import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfigurat import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.test.context.assertj.AssertableReactiveWebApplicationContext; import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; -import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory; import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext; +import org.springframework.boot.web.server.reactive.tomcat.TomcatReactiveWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/servlet/JerseyEndpointRequestIntegrationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/servlet/JerseyEndpointRequestIntegrationTests.java index d290c7b873..03593945d4 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/servlet/JerseyEndpointRequestIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/servlet/JerseyEndpointRequestIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,7 +25,7 @@ import org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/servlet/MvcEndpointRequestIntegrationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/servlet/MvcEndpointRequestIntegrationTests.java index b2d270d43e..ac9d5658b5 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/servlet/MvcEndpointRequestIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/servlet/MvcEndpointRequestIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,7 +25,7 @@ import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoC import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/mappings/MappingsEndpointReactiveDocumentationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/mappings/MappingsEndpointReactiveDocumentationTests.java index b801848014..2e2afffb43 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/mappings/MappingsEndpointReactiveDocumentationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/mappings/MappingsEndpointReactiveDocumentationTests.java @@ -32,7 +32,7 @@ import org.springframework.boot.actuate.web.mappings.reactive.DispatcherHandlers import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.netty.NettyReactiveWebServerFactory; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/mappings/MappingsEndpointServletDocumentationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/mappings/MappingsEndpointServletDocumentationTests.java index 08797a7fe1..b65ec10684 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/mappings/MappingsEndpointServletDocumentationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/mappings/MappingsEndpointServletDocumentationTests.java @@ -34,7 +34,7 @@ import org.springframework.boot.actuate.web.mappings.servlet.ServletsMappingDesc import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/reactive/ReactiveManagementChildContextConfigurationIntegrationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/reactive/ReactiveManagementChildContextConfigurationIntegrationTests.java index 94b1896ee3..110b637030 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/reactive/ReactiveManagementChildContextConfigurationIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/reactive/ReactiveManagementChildContextConfigurationIntegrationTests.java @@ -32,12 +32,13 @@ import org.junit.jupiter.api.io.TempDir; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.web.server.tomcat.TomcatReactiveManagementContextAutoConfiguration; import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration; -import org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration; import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.reactive.tomcat.TomcatReactiveWebServerAutoConfiguration; import org.springframework.boot.convert.ApplicationConversionService; import org.springframework.boot.env.ConfigTreePropertySource; import org.springframework.boot.test.context.assertj.AssertableReactiveWebApplicationContext; @@ -45,9 +46,9 @@ import org.springframework.boot.test.context.runner.ContextConsumer; import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; import org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer; import org.springframework.boot.web.context.WebServerInitializedEvent; -import org.springframework.boot.web.embedded.tomcat.TomcatWebServer; import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext; import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.tomcat.TomcatWebServer; import org.springframework.context.ApplicationListener; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.convert.support.ConfigurableConversionService; @@ -69,7 +70,7 @@ class ReactiveManagementChildContextConfigurationIntegrationTests { private final ReactiveWebApplicationContextRunner runner = new ReactiveWebApplicationContextRunner( AnnotationConfigReactiveWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(ManagementContextAutoConfiguration.class, - ReactiveWebServerFactoryAutoConfiguration.class, ReactiveManagementContextAutoConfiguration.class, + TomcatReactiveWebServerAutoConfiguration.class, TomcatReactiveManagementContextAutoConfiguration.class, WebEndpointAutoConfiguration.class, EndpointAutoConfiguration.class, HttpHandlerAutoConfiguration.class, WebFluxAutoConfiguration.class)) .withUserConfiguration(SucceedingEndpoint.class) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/server/ChildManagementContextInitializerAotTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/server/ChildManagementContextInitializerAotTests.java index cd6401d2a3..4208eb9e17 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/server/ChildManagementContextInitializerAotTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/server/ChildManagementContextInitializerAotTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,9 +25,10 @@ import org.springframework.aot.AotDetector; import org.springframework.aot.test.generate.TestGenerationContext; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.web.server.tomcat.TomcatServletManagementContextAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.boot.test.system.CapturedOutput; import org.springframework.boot.test.system.OutputCaptureExtension; @@ -50,8 +51,8 @@ import static org.assertj.core.api.Assertions.assertThat; * * @author Phillip Webb */ -@ExtendWith(OutputCaptureExtension.class) @DirtiesUrlFactories +@ExtendWith(OutputCaptureExtension.class) class ChildManagementContextInitializerAotTests { @Test @@ -61,8 +62,10 @@ class ChildManagementContextInitializerAotTests { WebApplicationContextRunner contextRunner = new WebApplicationContextRunner( AnnotationConfigServletWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(ManagementContextAutoConfiguration.class, - ServletWebServerFactoryAutoConfiguration.class, ServletManagementContextAutoConfiguration.class, - WebEndpointAutoConfiguration.class, EndpointAutoConfiguration.class)); + TomcatServletWebServerAutoConfiguration.class, + TomcatServletManagementContextAutoConfiguration.class, + ServletManagementContextAutoConfiguration.class, WebEndpointAutoConfiguration.class, + EndpointAutoConfiguration.class)); contextRunner.withPropertyValues("server.port=0", "management.server.port=0").prepare((context) -> { TestGenerationContext generationContext = new TestGenerationContext(TestTarget.class); ClassName className = new ApplicationContextAotGenerator().processAheadOfTime( diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/server/ManagementContextAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/server/ManagementContextAutoConfigurationTests.java index a617750be9..07edd2175c 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/server/ManagementContextAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/server/ManagementContextAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,10 +23,11 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.web.server.tomcat.TomcatServletManagementContextAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.boot.test.system.CapturedOutput; import org.springframework.boot.test.system.OutputCaptureExtension; @@ -49,8 +50,10 @@ class ManagementContextAutoConfigurationTests { WebApplicationContextRunner contextRunner = new WebApplicationContextRunner( AnnotationConfigServletWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(ManagementContextAutoConfiguration.class, - ServletWebServerFactoryAutoConfiguration.class, ServletManagementContextAutoConfiguration.class, - WebEndpointAutoConfiguration.class, EndpointAutoConfiguration.class)); + TomcatServletWebServerAutoConfiguration.class, + TomcatServletManagementContextAutoConfiguration.class, + ServletManagementContextAutoConfiguration.class, WebEndpointAutoConfiguration.class, + EndpointAutoConfiguration.class)); contextRunner.withPropertyValues("server.port=0", "management.server.port=0") .run((context) -> assertThat(output).satisfies(numberOfOccurrences("Tomcat started on port", 2))); } @@ -59,8 +62,10 @@ class ManagementContextAutoConfigurationTests { void childManagementContextShouldNotStartWithoutEmbeddedServer(CapturedOutput output) { WebApplicationContextRunner contextRunner = new WebApplicationContextRunner() .withConfiguration(AutoConfigurations.of(ManagementContextAutoConfiguration.class, - ServletWebServerFactoryAutoConfiguration.class, ServletManagementContextAutoConfiguration.class, - WebEndpointAutoConfiguration.class, EndpointAutoConfiguration.class)); + TomcatServletWebServerAutoConfiguration.class, + TomcatServletManagementContextAutoConfiguration.class, + ServletManagementContextAutoConfiguration.class, WebEndpointAutoConfiguration.class, + EndpointAutoConfiguration.class)); contextRunner.withPropertyValues("server.port=0", "management.server.port=0").run((context) -> { assertThat(context).hasNotFailed(); assertThat(output).doesNotContain("Tomcat started"); @@ -72,8 +77,10 @@ class ManagementContextAutoConfigurationTests { WebApplicationContextRunner contextRunner = new WebApplicationContextRunner( AnnotationConfigServletWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(ManagementContextAutoConfiguration.class, - ServletWebServerFactoryAutoConfiguration.class, ServletManagementContextAutoConfiguration.class, - WebEndpointAutoConfiguration.class, EndpointAutoConfiguration.class)); + TomcatServletWebServerAutoConfiguration.class, + TomcatServletManagementContextAutoConfiguration.class, + ServletManagementContextAutoConfiguration.class, WebEndpointAutoConfiguration.class, + EndpointAutoConfiguration.class)); contextRunner.withPropertyValues("server.port=0", "management.server.port=0").run((context) -> { assertThat(output).satisfies(numberOfOccurrences("Tomcat started on port", 2)); context.getSourceApplicationContext().stop(); @@ -87,7 +94,7 @@ class ManagementContextAutoConfigurationTests { WebApplicationContextRunner contextRunner = new WebApplicationContextRunner( AnnotationConfigServletWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(ManagementContextAutoConfiguration.class, - ServletWebServerFactoryAutoConfiguration.class, ServletManagementContextAutoConfiguration.class, + TomcatServletWebServerAutoConfiguration.class, ServletManagementContextAutoConfiguration.class, WebEndpointAutoConfiguration.class, EndpointAutoConfiguration.class, DispatcherServletAutoConfiguration.class)); contextRunner.withPropertyValues("server.port=0", "management.server.address=127.0.0.1") diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/servlet/WebMvcEndpointChildContextConfigurationIntegrationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/servlet/WebMvcEndpointChildContextConfigurationIntegrationTests.java index 22b1bb027d..247eb3eefc 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/servlet/WebMvcEndpointChildContextConfigurationIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/servlet/WebMvcEndpointChildContextConfigurationIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,11 +32,12 @@ import org.junit.jupiter.api.io.TempDir; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.web.server.tomcat.TomcatServletManagementContextAutoConfiguration; import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration; import org.springframework.boot.convert.ApplicationConversionService; import org.springframework.boot.env.ConfigTreePropertySource; @@ -70,9 +71,10 @@ class WebMvcEndpointChildContextConfigurationIntegrationTests { private final WebApplicationContextRunner runner = new WebApplicationContextRunner( AnnotationConfigServletWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(ManagementContextAutoConfiguration.class, - ServletWebServerFactoryAutoConfiguration.class, ServletManagementContextAutoConfiguration.class, - WebEndpointAutoConfiguration.class, EndpointAutoConfiguration.class, - DispatcherServletAutoConfiguration.class, ErrorMvcAutoConfiguration.class)) + TomcatServletWebServerAutoConfiguration.class, TomcatServletManagementContextAutoConfiguration.class, + ServletManagementContextAutoConfiguration.class, WebEndpointAutoConfiguration.class, + EndpointAutoConfiguration.class, DispatcherServletAutoConfiguration.class, + ErrorMvcAutoConfiguration.class)) .withUserConfiguration(SucceedingEndpoint.class, FailingEndpoint.class, FailingControllerEndpoint.class) .withInitializer(new ServerPortInfoApplicationContextInitializer()) .withPropertyValues("server.port=0", "management.server.port=0", "management.endpoints.web.exposure.include=*", diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/ServletEndpointRegistrar.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/ServletEndpointRegistrar.java index 3c82519d1c..5adb2b6360 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/ServletEndpointRegistrar.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/ServletEndpointRegistrar.java @@ -37,7 +37,7 @@ import org.apache.commons.logging.LogFactory; import org.springframework.boot.actuate.endpoint.Access; import org.springframework.boot.actuate.endpoint.EndpointAccessResolver; -import org.springframework.boot.web.servlet.ServletContextInitializer; +import org.springframework.boot.web.server.servlet.ServletContextInitializer; import org.springframework.util.Assert; import org.springframework.util.StringUtils; diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/jetty/AbstractJettyMetricsBinder.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/jetty/AbstractJettyMetricsBinder.java index 0d26c1816e..6b6faf1fae 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/jetty/AbstractJettyMetricsBinder.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/jetty/AbstractJettyMetricsBinder.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,8 +20,8 @@ import org.eclipse.jetty.server.Server; import org.springframework.boot.context.event.ApplicationStartedEvent; import org.springframework.boot.web.context.WebServerApplicationContext; -import org.springframework.boot.web.embedded.jetty.JettyWebServer; import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.jetty.JettyWebServer; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationListener; diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/tomcat/TomcatMetricsBinder.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/tomcat/TomcatMetricsBinder.java index fb58802647..fd9a313db3 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/tomcat/TomcatMetricsBinder.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/tomcat/TomcatMetricsBinder.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,8 +28,8 @@ import org.apache.catalina.Manager; import org.springframework.beans.factory.DisposableBean; import org.springframework.boot.context.event.ApplicationStartedEvent; import org.springframework.boot.web.context.WebServerApplicationContext; -import org.springframework.boot.web.embedded.tomcat.TomcatWebServer; import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.tomcat.TomcatWebServer; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationListener; diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/web/mappings/servlet/DispatcherServletHandlerMappings.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/web/mappings/servlet/DispatcherServletHandlerMappings.java index e5b1c36b4f..aa0389dfd4 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/web/mappings/servlet/DispatcherServletHandlerMappings.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/web/mappings/servlet/DispatcherServletHandlerMappings.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,9 +26,9 @@ import org.apache.catalina.Container; import org.apache.catalina.Context; import org.apache.catalina.core.StandardWrapper; -import org.springframework.boot.web.embedded.tomcat.TomcatWebServer; -import org.springframework.boot.web.embedded.undertow.UndertowServletWebServer; import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.servlet.undertow.UndertowServletWebServer; +import org.springframework.boot.web.server.tomcat.TomcatWebServer; import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/annotation/BaseConfiguration.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/annotation/BaseConfiguration.java index f02671d1ab..27a7e947ca 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/annotation/BaseConfiguration.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/annotation/BaseConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,7 +25,7 @@ import org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper; import org.springframework.boot.actuate.endpoint.invoke.convert.ConversionServiceParameterValueMapper; import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes; import org.springframework.boot.actuate.endpoint.web.PathMapper; -import org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader; +import org.springframework.boot.web.server.tomcat.TomcatEmbeddedWebappClassLoader; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/jersey/JerseyWebEndpointIntegrationTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/jersey/JerseyWebEndpointIntegrationTests.java index 528885a002..7a3fe003ff 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/jersey/JerseyWebEndpointIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/jersey/JerseyWebEndpointIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,7 +40,7 @@ import org.springframework.boot.actuate.endpoint.web.EndpointMapping; import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes; import org.springframework.boot.actuate.endpoint.web.annotation.AbstractWebEndpointIntegrationTests; import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.context.annotation.Bean; diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/reactive/ControllerEndpointHandlerMappingIntegrationTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/reactive/ControllerEndpointHandlerMappingIntegrationTests.java index 6fc0654e34..2a67496790 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/reactive/ControllerEndpointHandlerMappingIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/reactive/ControllerEndpointHandlerMappingIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,8 +37,8 @@ import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfigurat import org.springframework.boot.test.context.assertj.AssertableReactiveWebApplicationContext; import org.springframework.boot.test.context.runner.ContextConsumer; import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; -import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext; +import org.springframework.boot.web.server.reactive.netty.NettyReactiveWebServerFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/reactive/WebFluxEndpointIntegrationTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/reactive/WebFluxEndpointIntegrationTests.java index f27d667e57..bd8f87d9f0 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/reactive/WebFluxEndpointIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/reactive/WebFluxEndpointIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,9 +27,9 @@ import org.springframework.boot.actuate.endpoint.web.annotation.AbstractWebEndpo import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration; -import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext; import org.springframework.boot.web.reactive.context.ReactiveWebServerInitializedEvent; +import org.springframework.boot.web.server.reactive.netty.NettyReactiveWebServerFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.Bean; diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/servlet/ControllerEndpointHandlerMappingIntegrationTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/servlet/ControllerEndpointHandlerMappingIntegrationTests.java index d9ad24f73a..840f7a9096 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/servlet/ControllerEndpointHandlerMappingIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/servlet/ControllerEndpointHandlerMappingIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,7 +38,7 @@ import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguratio import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext; import org.springframework.boot.test.context.runner.ContextConsumer; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/servlet/MvcWebEndpointIntegrationTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/servlet/MvcWebEndpointIntegrationTests.java index 3cbca88dd6..ea8dc2d7ae 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/servlet/MvcWebEndpointIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/servlet/MvcWebEndpointIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,11 +34,11 @@ import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDisco import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -132,7 +132,7 @@ class MvcWebEndpointIntegrationTests @Configuration(proxyBeanMethods = false) @ImportAutoConfiguration({ JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, - ServletWebServerFactoryAutoConfiguration.class, WebMvcAutoConfiguration.class, + TomcatServletWebServerAutoConfiguration.class, WebMvcAutoConfiguration.class, DispatcherServletAutoConfiguration.class, ErrorMvcAutoConfiguration.class }) static class WebMvcConfiguration { @@ -157,7 +157,7 @@ class MvcWebEndpointIntegrationTests @Configuration(proxyBeanMethods = false) @ImportAutoConfiguration({ JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, - ServletWebServerFactoryAutoConfiguration.class, WebMvcAutoConfiguration.class, + TomcatServletWebServerAutoConfiguration.class, WebMvcAutoConfiguration.class, DispatcherServletAutoConfiguration.class, ErrorMvcAutoConfiguration.class }) static class PathMatcherWebMvcConfiguration { diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/test/WebEndpointTestInvocationContextProvider.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/test/WebEndpointTestInvocationContextProvider.java index 2327785100..829a2cd3b3 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/test/WebEndpointTestInvocationContextProvider.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/test/WebEndpointTestInvocationContextProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -56,9 +56,9 @@ import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfigurat import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; import org.springframework.boot.web.context.WebServerInitializedEvent; -import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext; +import org.springframework.boot.web.server.reactive.netty.NettyReactiveWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationListener; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/dockerTest/java/org/springframework/boot/autoconfigure/pulsar/PulsarAutoConfigurationIntegrationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/dockerTest/java/org/springframework/boot/autoconfigure/pulsar/PulsarAutoConfigurationIntegrationTests.java index b95f8477dc..d0ec406666 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/dockerTest/java/org/springframework/boot/autoconfigure/pulsar/PulsarAutoConfigurationIntegrationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/dockerTest/java/org/springframework/boot/autoconfigure/pulsar/PulsarAutoConfigurationIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,8 +28,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; @@ -82,7 +82,7 @@ class PulsarAutoConfigurationIntegrationTests { } @Configuration(proxyBeanMethods = false) - @ImportAutoConfiguration({ DispatcherServletAutoConfiguration.class, ServletWebServerFactoryAutoConfiguration.class, + @ImportAutoConfiguration({ DispatcherServletAutoConfiguration.class, TomcatServletWebServerAutoConfiguration.class, WebMvcAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, JacksonAutoConfiguration.class, PulsarAutoConfiguration.class, PulsarReactiveAutoConfiguration.class }) @Import(TestWebController.class) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/EnableAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/EnableAutoConfiguration.java index 83a15b7877..c7ad89e527 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/EnableAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/EnableAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,8 +27,8 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.annotation.ImportCandidates; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; -import org.springframework.boot.web.servlet.server.ServletWebServerFactory; +import org.springframework.boot.web.server.servlet.ServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/rsocket/RSocketServerAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/rsocket/RSocketServerAutoConfiguration.java index 70b62631ef..5b03571e47 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/rsocket/RSocketServerAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/rsocket/RSocketServerAutoConfiguration.java @@ -56,8 +56,8 @@ import org.springframework.util.unit.DataSize; * {@link EnableAutoConfiguration Auto-configuration} for RSocket servers. In the case of * {@link org.springframework.boot.WebApplicationType#REACTIVE}, the RSocket server is * added as a WebSocket endpoint on the existing - * {@link org.springframework.boot.web.embedded.netty.NettyWebServer}. If a specific - * server port is configured, a new standalone RSocket server is created. + * {@link org.springframework.boot.web.server.reactive.netty.NettyWebServer}. If a + * specific server port is configured, a new standalone RSocket server is created. * * @author Brian Clozel * @author Scott Frederick diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/rsocket/RSocketWebSocketNettyRouteProvider.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/rsocket/RSocketWebSocketNettyRouteProvider.java index f70f9d41d5..2d473e9e8c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/rsocket/RSocketWebSocketNettyRouteProvider.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/rsocket/RSocketWebSocketNettyRouteProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,7 @@ import reactor.netty.http.server.WebsocketServerSpec; import reactor.netty.http.server.WebsocketServerSpec.Builder; import org.springframework.boot.rsocket.server.RSocketServerCustomizer; -import org.springframework.boot.web.embedded.netty.NettyRouteProvider; +import org.springframework.boot.web.server.reactive.netty.NettyRouteProvider; /** * {@link NettyRouteProvider} that configures an RSocket Websocket endpoint. diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java index 0f42e0f656..8ac383fbd5 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java @@ -41,8 +41,8 @@ import org.springframework.boot.web.server.Http2; import org.springframework.boot.web.server.MimeMappings; import org.springframework.boot.web.server.Shutdown; import org.springframework.boot.web.server.Ssl; -import org.springframework.boot.web.servlet.server.Jsp; -import org.springframework.boot.web.servlet.server.Session; +import org.springframework.boot.web.server.servlet.Jsp; +import org.springframework.boot.web.server.servlet.Session; import org.springframework.util.StringUtils; import org.springframework.util.unit.DataSize; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/EmbeddedWebServerFactoryCustomizerAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/EmbeddedWebServerFactoryCustomizerAutoConfiguration.java deleted file mode 100644 index aef7f80361..0000000000 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/EmbeddedWebServerFactoryCustomizerAutoConfiguration.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2012-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.autoconfigure.web.embedded; - -import io.undertow.Undertow; -import org.apache.catalina.startup.Tomcat; -import org.apache.coyote.UpgradeProtocol; -import org.eclipse.jetty.ee10.webapp.WebAppContext; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.util.Loader; -import org.xnio.SslClientAuthMode; -import reactor.netty.http.server.HttpServer; - -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWarDeployment; -import org.springframework.boot.autoconfigure.condition.ConditionalOnThreading; -import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; -import org.springframework.boot.autoconfigure.thread.Threading; -import org.springframework.boot.autoconfigure.web.ServerProperties; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.web.embedded.undertow.UndertowDeploymentInfoCustomizer; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.env.Environment; -import org.springframework.core.task.VirtualThreadTaskExecutor; - -/** - * {@link EnableAutoConfiguration Auto-configuration} for embedded servlet and reactive - * web servers customizations. - * - * @author Phillip Webb - * @author Moritz Halbritter - * @since 2.0.0 - */ -@AutoConfiguration -@ConditionalOnNotWarDeployment -@ConditionalOnWebApplication -@EnableConfigurationProperties(ServerProperties.class) -public class EmbeddedWebServerFactoryCustomizerAutoConfiguration { - - /** - * Nested configuration if Tomcat is being used. - */ - @Configuration(proxyBeanMethods = false) - @ConditionalOnClass({ Tomcat.class, UpgradeProtocol.class }) - public static class TomcatWebServerFactoryCustomizerConfiguration { - - @Bean - public TomcatWebServerFactoryCustomizer tomcatWebServerFactoryCustomizer(Environment environment, - ServerProperties serverProperties) { - return new TomcatWebServerFactoryCustomizer(environment, serverProperties); - } - - @Bean - @ConditionalOnThreading(Threading.VIRTUAL) - TomcatVirtualThreadsWebServerFactoryCustomizer tomcatVirtualThreadsProtocolHandlerCustomizer() { - return new TomcatVirtualThreadsWebServerFactoryCustomizer(); - } - - } - - /** - * Nested configuration if Jetty is being used. - */ - @Configuration(proxyBeanMethods = false) - @ConditionalOnClass({ Server.class, Loader.class, WebAppContext.class }) - public static class JettyWebServerFactoryCustomizerConfiguration { - - @Bean - public JettyWebServerFactoryCustomizer jettyWebServerFactoryCustomizer(Environment environment, - ServerProperties serverProperties) { - return new JettyWebServerFactoryCustomizer(environment, serverProperties); - } - - @Bean - @ConditionalOnThreading(Threading.VIRTUAL) - JettyVirtualThreadsWebServerFactoryCustomizer jettyVirtualThreadsWebServerFactoryCustomizer( - ServerProperties serverProperties) { - return new JettyVirtualThreadsWebServerFactoryCustomizer(serverProperties); - } - - } - - /** - * Nested configuration if Undertow is being used. - */ - @Configuration(proxyBeanMethods = false) - @ConditionalOnClass({ Undertow.class, SslClientAuthMode.class }) - public static class UndertowWebServerFactoryCustomizerConfiguration { - - @Bean - public UndertowWebServerFactoryCustomizer undertowWebServerFactoryCustomizer(Environment environment, - ServerProperties serverProperties) { - return new UndertowWebServerFactoryCustomizer(environment, serverProperties); - } - - @Bean - @ConditionalOnThreading(Threading.VIRTUAL) - UndertowDeploymentInfoCustomizer virtualThreadsUndertowDeploymentInfoCustomizer() { - return (deploymentInfo) -> deploymentInfo.setExecutor(new VirtualThreadTaskExecutor("undertow-")); - } - - } - - /** - * Nested configuration if Netty is being used. - */ - @Configuration(proxyBeanMethods = false) - @ConditionalOnClass(HttpServer.class) - public static class NettyWebServerFactoryCustomizerConfiguration { - - @Bean - public NettyWebServerFactoryCustomizer nettyWebServerFactoryCustomizer(Environment environment, - ServerProperties serverProperties) { - return new NettyWebServerFactoryCustomizer(environment, serverProperties); - } - - } - -} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/ReactiveWebServerFactoryConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/ReactiveWebServerFactoryConfiguration.java deleted file mode 100644 index 74880e24d3..0000000000 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/ReactiveWebServerFactoryConfiguration.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2012-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.autoconfigure.web.reactive; - -import io.undertow.Undertow; -import org.eclipse.jetty.ee10.servlet.ServletHolder; -import reactor.netty.http.server.HttpServer; - -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.reactor.netty.ReactorNettyConfigurations; -import org.springframework.boot.web.embedded.jetty.JettyReactiveWebServerFactory; -import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer; -import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; -import org.springframework.boot.web.embedded.netty.NettyRouteProvider; -import org.springframework.boot.web.embedded.netty.NettyServerCustomizer; -import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer; -import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer; -import org.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer; -import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory; -import org.springframework.boot.web.embedded.undertow.UndertowBuilderCustomizer; -import org.springframework.boot.web.embedded.undertow.UndertowReactiveWebServerFactory; -import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.http.client.ReactorResourceFactory; - -/** - * Configuration classes for reactive web servers - *

- * Those should be {@code @Import} in a regular auto-configuration class to guarantee - * their order of execution. - * - * @author Brian Clozel - * @author Raheela Aslam - * @author Sergey Serdyuk - */ -abstract class ReactiveWebServerFactoryConfiguration { - - @Configuration(proxyBeanMethods = false) - @ConditionalOnMissingBean(ReactiveWebServerFactory.class) - @ConditionalOnClass({ HttpServer.class }) - @Import(ReactorNettyConfigurations.ReactorResourceFactoryConfiguration.class) - static class EmbeddedNetty { - - @Bean - NettyReactiveWebServerFactory nettyReactiveWebServerFactory(ReactorResourceFactory resourceFactory, - ObjectProvider routes, ObjectProvider serverCustomizers) { - NettyReactiveWebServerFactory serverFactory = new NettyReactiveWebServerFactory(); - serverFactory.setResourceFactory(resourceFactory); - routes.orderedStream().forEach(serverFactory::addRouteProviders); - serverFactory.getServerCustomizers().addAll(serverCustomizers.orderedStream().toList()); - return serverFactory; - } - - } - - @Configuration(proxyBeanMethods = false) - @ConditionalOnMissingBean(ReactiveWebServerFactory.class) - @ConditionalOnClass({ org.apache.catalina.startup.Tomcat.class }) - static class EmbeddedTomcat { - - @Bean - TomcatReactiveWebServerFactory tomcatReactiveWebServerFactory( - ObjectProvider connectorCustomizers, - ObjectProvider contextCustomizers, - ObjectProvider> protocolHandlerCustomizers) { - TomcatReactiveWebServerFactory factory = new TomcatReactiveWebServerFactory(); - factory.getTomcatConnectorCustomizers().addAll(connectorCustomizers.orderedStream().toList()); - factory.getTomcatContextCustomizers().addAll(contextCustomizers.orderedStream().toList()); - factory.getTomcatProtocolHandlerCustomizers().addAll(protocolHandlerCustomizers.orderedStream().toList()); - return factory; - } - - } - - @Configuration(proxyBeanMethods = false) - @ConditionalOnMissingBean(ReactiveWebServerFactory.class) - @ConditionalOnClass({ org.eclipse.jetty.server.Server.class, ServletHolder.class }) - static class EmbeddedJetty { - - @Bean - JettyReactiveWebServerFactory jettyReactiveWebServerFactory( - ObjectProvider serverCustomizers) { - JettyReactiveWebServerFactory serverFactory = new JettyReactiveWebServerFactory(); - serverFactory.getServerCustomizers().addAll(serverCustomizers.orderedStream().toList()); - return serverFactory; - } - - } - - @Configuration(proxyBeanMethods = false) - @ConditionalOnMissingBean(ReactiveWebServerFactory.class) - @ConditionalOnClass({ Undertow.class }) - static class EmbeddedUndertow { - - @Bean - UndertowReactiveWebServerFactory undertowReactiveWebServerFactory( - ObjectProvider builderCustomizers) { - UndertowReactiveWebServerFactory factory = new UndertowReactiveWebServerFactory(); - factory.getBuilderCustomizers().addAll(builderCustomizers.orderedStream().toList()); - return factory; - } - - } - -} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java index 0ba0a8ef48..0530f197fd 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java @@ -106,9 +106,8 @@ import org.springframework.web.server.session.WebSessionManager; * @author Weix Sun * @since 2.0.0 */ -@AutoConfiguration(after = { ReactiveWebServerFactoryAutoConfiguration.class, CodecsAutoConfiguration.class, - ReactiveMultipartAutoConfiguration.class, ValidationAutoConfiguration.class, - WebSessionIdResolverAutoConfiguration.class }) +@AutoConfiguration(after = { CodecsAutoConfiguration.class, ReactiveMultipartAutoConfiguration.class, + ValidationAutoConfiguration.class, WebSessionIdResolverAutoConfiguration.class }) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE) @ConditionalOnClass(WebFluxConfigurer.class) @ConditionalOnMissingBean({ WebFluxConfigurationSupport.class }) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/JettyThreadPool.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/jetty/JettyThreadPool.java similarity index 94% rename from spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/JettyThreadPool.java rename to spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/jetty/JettyThreadPool.java index 7c8dadadb9..ccf72f6be2 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/JettyThreadPool.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/jetty/JettyThreadPool.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.web.embedded; +package org.springframework.boot.autoconfigure.web.server.jetty; import java.util.concurrent.BlockingQueue; import java.util.concurrent.SynchronousQueue; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/JettyVirtualThreadsWebServerFactoryCustomizer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/jetty/JettyVirtualThreadsWebServerFactoryCustomizer.java similarity index 89% rename from spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/JettyVirtualThreadsWebServerFactoryCustomizer.java rename to spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/jetty/JettyVirtualThreadsWebServerFactoryCustomizer.java index c54e308cd9..78a8f66e2a 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/JettyVirtualThreadsWebServerFactoryCustomizer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/jetty/JettyVirtualThreadsWebServerFactoryCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,14 +14,14 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.web.embedded; +package org.springframework.boot.autoconfigure.web.server.jetty; import org.eclipse.jetty.util.VirtualThreads; import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.springframework.boot.autoconfigure.web.ServerProperties; -import org.springframework.boot.web.embedded.jetty.ConfigurableJettyWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.jetty.ConfigurableJettyWebServerFactory; import org.springframework.core.Ordered; import org.springframework.util.Assert; @@ -29,7 +29,7 @@ import org.springframework.util.Assert; * Activates virtual threads on the {@link ConfigurableJettyWebServerFactory}. * * @author Moritz Halbritter - * @since 3.2.0 + * @since 4.0.0 */ public class JettyVirtualThreadsWebServerFactoryCustomizer implements WebServerFactoryCustomizer, Ordered { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/jetty/JettyWebServerConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/jetty/JettyWebServerConfiguration.java new file mode 100644 index 0000000000..2ab7f92da4 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/jetty/JettyWebServerConfiguration.java @@ -0,0 +1,54 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.web.server.jetty; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWarDeployment; +import org.springframework.boot.autoconfigure.condition.ConditionalOnThreading; +import org.springframework.boot.autoconfigure.thread.Threading; +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.autoconfigure.web.server.reactive.jetty.JettyReactiveWebServerAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.jetty.JettyServletWebServerAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +/** + * {@link Configuration Configuration} for a Jetty-based reactive or servlet web server. + * + * @author Andy Wilkinson + * @since 4.0.0 + * @see JettyReactiveWebServerAutoConfiguration + * @see JettyServletWebServerAutoConfiguration + */ +@ConditionalOnNotWarDeployment +@Configuration(proxyBeanMethods = false) +public class JettyWebServerConfiguration { + + @Bean + JettyWebServerFactoryCustomizer jettyWebServerFactoryCustomizer(Environment environment, + ServerProperties serverProperties) { + return new JettyWebServerFactoryCustomizer(environment, serverProperties); + } + + @Bean + @ConditionalOnThreading(Threading.VIRTUAL) + JettyVirtualThreadsWebServerFactoryCustomizer jettyVirtualThreadsWebServerFactoryCustomizer( + ServerProperties serverProperties) { + return new JettyVirtualThreadsWebServerFactoryCustomizer(serverProperties); + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/JettyWebServerFactoryCustomizer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/jetty/JettyWebServerFactoryCustomizer.java similarity index 98% rename from spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/JettyWebServerFactoryCustomizer.java rename to spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/jetty/JettyWebServerFactoryCustomizer.java index 9c4e60ff4b..53441058af 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/JettyWebServerFactoryCustomizer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/jetty/JettyWebServerFactoryCustomizer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.web.embedded; +package org.springframework.boot.autoconfigure.web.server.jetty; import java.time.Duration; import java.util.Arrays; @@ -36,8 +36,8 @@ import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.autoconfigure.web.ServerProperties.Jetty.Accesslog.Format; import org.springframework.boot.cloud.CloudPlatform; import org.springframework.boot.context.properties.PropertyMapper; -import org.springframework.boot.web.embedded.jetty.ConfigurableJettyWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.jetty.ConfigurableJettyWebServerFactory; import org.springframework.core.Ordered; import org.springframework.core.env.Environment; import org.springframework.util.CollectionUtils; @@ -52,7 +52,7 @@ import org.springframework.util.unit.DataSize; * @author Rafiullah Hamedy * @author Florian Storz * @author Michael Weidmann - * @since 2.0.0 + * @since 4.0.0 */ public class JettyWebServerFactoryCustomizer implements WebServerFactoryCustomizer, Ordered { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/jetty/package-info.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/jetty/package-info.java new file mode 100644 index 0000000000..2aac318d85 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/jetty/package-info.java @@ -0,0 +1,21 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Classes related to the auto-configuration of a servlet or reactive web server using + * Jetty. + */ +package org.springframework.boot.autoconfigure.web.server.jetty; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/ReactiveWebServerFactoryAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/ReactiveWebServerConfiguration.java similarity index 71% rename from spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/ReactiveWebServerFactoryAutoConfiguration.java rename to spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/ReactiveWebServerConfiguration.java index 806cadedd0..53e88ed185 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/ReactiveWebServerFactoryAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/ReactiveWebServerConfiguration.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.web.reactive; +package org.springframework.boot.autoconfigure.web.server.reactive; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; @@ -23,44 +23,31 @@ import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigureOrder; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.ssl.SslBundles; import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; -import org.springframework.core.Ordered; import org.springframework.core.type.AnnotationMetadata; -import org.springframework.http.ReactiveHttpInputMessage; import org.springframework.util.ObjectUtils; import org.springframework.web.server.adapter.ForwardedHeaderTransformer; /** - * {@link EnableAutoConfiguration Auto-configuration} for a reactive web server. + * {@link Configuration Configuration} for a reactive web server. * * @author Brian Clozel * @author Scott Frederick - * @since 2.0.0 + * @since 4.0.0 */ -@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) -@AutoConfiguration -@ConditionalOnClass(ReactiveHttpInputMessage.class) -@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE) +@Configuration(proxyBeanMethods = false) @EnableConfigurationProperties(ServerProperties.class) -@Import({ ReactiveWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class, - ReactiveWebServerFactoryConfiguration.EmbeddedTomcat.class, - ReactiveWebServerFactoryConfiguration.EmbeddedJetty.class, - ReactiveWebServerFactoryConfiguration.EmbeddedUndertow.class, - ReactiveWebServerFactoryConfiguration.EmbeddedNetty.class }) -public class ReactiveWebServerFactoryAutoConfiguration { +@Import(ReactiveWebServerConfiguration.BeanPostProcessorsRegistrar.class) +public class ReactiveWebServerConfiguration { @Bean public ReactiveWebServerFactoryCustomizer reactiveWebServerFactoryCustomizer(ServerProperties serverProperties, @@ -68,13 +55,6 @@ public class ReactiveWebServerFactoryAutoConfiguration { return new ReactiveWebServerFactoryCustomizer(serverProperties, sslBundles.getIfAvailable()); } - @Bean - @ConditionalOnClass(name = "org.apache.catalina.startup.Tomcat") - public TomcatReactiveWebServerFactoryCustomizer tomcatReactiveWebServerFactoryCustomizer( - ServerProperties serverProperties) { - return new TomcatReactiveWebServerFactoryCustomizer(serverProperties); - } - @Bean @ConditionalOnMissingBean @ConditionalOnProperty(name = "server.forward-headers-strategy", havingValue = "framework") diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/ReactiveWebServerFactoryCustomizer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/ReactiveWebServerFactoryCustomizer.java similarity index 92% rename from spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/ReactiveWebServerFactoryCustomizer.java rename to spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/ReactiveWebServerFactoryCustomizer.java index 1b1a1c7882..c5dadeda9f 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/ReactiveWebServerFactoryCustomizer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/ReactiveWebServerFactoryCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,13 +14,13 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.web.reactive; +package org.springframework.boot.autoconfigure.web.server.reactive; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.boot.ssl.SslBundles; -import org.springframework.boot.web.reactive.server.ConfigurableReactiveWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.reactive.ConfigurableReactiveWebServerFactory; import org.springframework.core.Ordered; /** @@ -30,7 +30,7 @@ import org.springframework.core.Ordered; * @author Brian Clozel * @author Yunkun Huang * @author Scott Frederick - * @since 2.0.0 + * @since 4.0.0 */ public class ReactiveWebServerFactoryCustomizer implements WebServerFactoryCustomizer, Ordered { @@ -51,7 +51,7 @@ public class ReactiveWebServerFactoryCustomizer * Create a new {@link ReactiveWebServerFactoryCustomizer} instance. * @param serverProperties the server properties * @param sslBundles the SSL bundles - * @since 3.1.0 + * @since 4.0.0 */ public ReactiveWebServerFactoryCustomizer(ServerProperties serverProperties, SslBundles sslBundles) { this.serverProperties = serverProperties; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/jetty/JettyReactiveWebServerAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/jetty/JettyReactiveWebServerAutoConfiguration.java new file mode 100644 index 0000000000..0ddf9114d8 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/jetty/JettyReactiveWebServerAutoConfiguration.java @@ -0,0 +1,73 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.web.server.reactive.jetty; + +import org.eclipse.jetty.ee10.servlet.ServletHolder; +import org.eclipse.jetty.ee10.websocket.jakarta.server.config.JakartaWebSocketServletContainerInitializer; +import org.eclipse.jetty.server.Server; + +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.autoconfigure.web.server.jetty.JettyWebServerConfiguration; +import org.springframework.boot.autoconfigure.web.server.reactive.ReactiveWebServerConfiguration; +import org.springframework.boot.web.server.jetty.JettyServerCustomizer; +import org.springframework.boot.web.server.reactive.ReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.jetty.JettyReactiveWebServerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.http.ReactiveHttpInputMessage; + +/** + * {@link EnableAutoConfiguration Auto-configuration} for a Jetty-based reactive web + * server. + * + * @author Andy Wilkinson + * @since 4.0.0 + */ +@AutoConfiguration +@ConditionalOnClass({ Server.class, ServletHolder.class, ReactiveHttpInputMessage.class }) +@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE) +@Import({ JettyWebServerConfiguration.class, ReactiveWebServerConfiguration.class }) +public class JettyReactiveWebServerAutoConfiguration { + + @Bean + @ConditionalOnMissingBean(ReactiveWebServerFactory.class) + JettyReactiveWebServerFactory jettyReactiveWebServerFactory( + ObjectProvider serverCustomizers) { + JettyReactiveWebServerFactory serverFactory = new JettyReactiveWebServerFactory(); + serverFactory.getServerCustomizers().addAll(serverCustomizers.orderedStream().toList()); + return serverFactory; + } + + @Configuration(proxyBeanMethods = false) + @ConditionalOnClass(JakartaWebSocketServletContainerInitializer.class) + static class JettyWebSocketConfiguration { + + @Bean + @ConditionalOnMissingBean(name = "websocketReactiveWebServerCustomizer") + WebSocketJettyReactiveWebServerFactoryCustomizer websocketServletWebServerCustomizer() { + return new WebSocketJettyReactiveWebServerFactoryCustomizer(); + } + + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/reactive/JettyWebSocketReactiveWebServerCustomizer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/jetty/WebSocketJettyReactiveWebServerFactoryCustomizer.java similarity index 91% rename from spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/reactive/JettyWebSocketReactiveWebServerCustomizer.java rename to spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/jetty/WebSocketJettyReactiveWebServerFactoryCustomizer.java index 00ca570b9d..58eececec1 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/reactive/JettyWebSocketReactiveWebServerCustomizer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/jetty/WebSocketJettyReactiveWebServerFactoryCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.websocket.reactive; +package org.springframework.boot.autoconfigure.web.server.reactive.jetty; import jakarta.servlet.ServletContext; import org.eclipse.jetty.ee10.servlet.ServletContextHandler; @@ -25,17 +25,17 @@ import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.websocket.core.server.WebSocketMappings; import org.eclipse.jetty.websocket.core.server.WebSocketServerComponents; -import org.springframework.boot.web.embedded.jetty.JettyReactiveWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.reactive.jetty.JettyReactiveWebServerFactory; import org.springframework.core.Ordered; /** * WebSocket customizer for {@link JettyReactiveWebServerFactory}. * * @author Andy Wilkinson - * @since 3.0.8 + * @since 4.0.0 */ -public class JettyWebSocketReactiveWebServerCustomizer +public class WebSocketJettyReactiveWebServerFactoryCustomizer implements WebServerFactoryCustomizer, Ordered { @Override diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/jetty/package-info.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/jetty/package-info.java new file mode 100644 index 0000000000..f41e8fc70a --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/jetty/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Classes related to the auto-configuration of a reactive web server using Jetty. + */ +package org.springframework.boot.autoconfigure.web.server.reactive.jetty; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/netty/NettyReactiveWebServerAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/netty/NettyReactiveWebServerAutoConfiguration.java new file mode 100644 index 0000000000..dcf3889b5a --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/netty/NettyReactiveWebServerAutoConfiguration.java @@ -0,0 +1,68 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.web.server.reactive.netty; + +import reactor.netty.http.server.HttpServer; + +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.reactor.netty.ReactorNettyConfigurations.ReactorResourceFactoryConfiguration; +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.autoconfigure.web.server.reactive.ReactiveWebServerConfiguration; +import org.springframework.boot.web.server.reactive.ReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.netty.NettyReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.netty.NettyRouteProvider; +import org.springframework.boot.web.server.reactive.netty.NettyServerCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; +import org.springframework.core.env.Environment; +import org.springframework.http.ReactiveHttpInputMessage; +import org.springframework.http.client.ReactorResourceFactory; + +/** + * {@link EnableAutoConfiguration Auto-configuration} for a Netty-based reactive web + * server. + * + * @author Andy Wilkinson + * @since 4.0.0 + */ +@AutoConfiguration +@ConditionalOnClass({ ReactiveHttpInputMessage.class, HttpServer.class }) +@Import({ ReactiveWebServerConfiguration.class, ReactorResourceFactoryConfiguration.class }) +public class NettyReactiveWebServerAutoConfiguration { + + @Bean + @ConditionalOnMissingBean(ReactiveWebServerFactory.class) + NettyReactiveWebServerFactory nettyReactiveWebServerFactory(ReactorResourceFactory resourceFactory, + ObjectProvider routes, ObjectProvider serverCustomizers) { + NettyReactiveWebServerFactory serverFactory = new NettyReactiveWebServerFactory(); + serverFactory.setResourceFactory(resourceFactory); + routes.orderedStream().forEach(serverFactory::addRouteProviders); + serverFactory.getServerCustomizers().addAll(serverCustomizers.orderedStream().toList()); + return serverFactory; + } + + @Bean + NettyReactiveWebServerFactoryCustomizer nettyWebServerFactoryCustomizer(Environment environment, + ServerProperties serverProperties) { + return new NettyReactiveWebServerFactoryCustomizer(environment, serverProperties); + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/NettyWebServerFactoryCustomizer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/netty/NettyReactiveWebServerFactoryCustomizer.java similarity index 92% rename from spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/NettyWebServerFactoryCustomizer.java rename to spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/netty/NettyReactiveWebServerFactoryCustomizer.java index 6dc657b3d7..e6d92de7be 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/NettyWebServerFactoryCustomizer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/netty/NettyReactiveWebServerFactoryCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.web.embedded; +package org.springframework.boot.autoconfigure.web.server.reactive.netty; import java.time.Duration; @@ -23,8 +23,8 @@ import io.netty.channel.ChannelOption; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.cloud.CloudPlatform; import org.springframework.boot.context.properties.PropertyMapper; -import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.reactive.netty.NettyReactiveWebServerFactory; import org.springframework.core.Ordered; import org.springframework.core.env.Environment; @@ -34,16 +34,16 @@ import org.springframework.core.env.Environment; * @author Brian Clozel * @author Chentao Qu * @author Artsiom Yudovin - * @since 2.1.0 + * @since 4.0.0 */ -public class NettyWebServerFactoryCustomizer +public class NettyReactiveWebServerFactoryCustomizer implements WebServerFactoryCustomizer, Ordered { private final Environment environment; private final ServerProperties serverProperties; - public NettyWebServerFactoryCustomizer(Environment environment, ServerProperties serverProperties) { + public NettyReactiveWebServerFactoryCustomizer(Environment environment, ServerProperties serverProperties) { this.environment = environment; this.serverProperties = serverProperties; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/netty/package-info.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/netty/package-info.java new file mode 100644 index 0000000000..e9c76b9226 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/netty/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Classes related to the auto-configuration of a reactive web server using Netty. + */ +package org.springframework.boot.autoconfigure.web.server.reactive.netty; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/package-info.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/package-info.java new file mode 100644 index 0000000000..2901a703b4 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Classes related to the auto-configuration of a reactive web server. + */ +package org.springframework.boot.autoconfigure.web.server.reactive; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/tomcat/TomcatReactiveWebServerAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/tomcat/TomcatReactiveWebServerAutoConfiguration.java new file mode 100644 index 0000000000..2a509b186a --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/tomcat/TomcatReactiveWebServerAutoConfiguration.java @@ -0,0 +1,71 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.web.server.reactive.tomcat; + +import org.apache.catalina.startup.Tomcat; + +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.autoconfigure.web.server.reactive.ReactiveWebServerConfiguration; +import org.springframework.boot.autoconfigure.web.server.tomcat.TomcatWebServerConfiguration; +import org.springframework.boot.web.server.reactive.ReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.tomcat.TomcatReactiveWebServerFactory; +import org.springframework.boot.web.server.tomcat.TomcatConnectorCustomizer; +import org.springframework.boot.web.server.tomcat.TomcatContextCustomizer; +import org.springframework.boot.web.server.tomcat.TomcatProtocolHandlerCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; +import org.springframework.http.ReactiveHttpInputMessage; + +/** + * {@link EnableAutoConfiguration Auto-configuration} for a Tomcat-based reactive web + * server. + * + * @author Andy Wilkinson + * @since 4.0.0 + */ +@AutoConfiguration +@ConditionalOnClass({ ReactiveHttpInputMessage.class, Tomcat.class }) +@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE) +@Import({ TomcatWebServerConfiguration.class, ReactiveWebServerConfiguration.class }) +public class TomcatReactiveWebServerAutoConfiguration { + + @Bean + TomcatReactiveWebServerFactoryCustomizer tomcatReactiveWebServerFactoryCustomizer( + ServerProperties serverProperties) { + return new TomcatReactiveWebServerFactoryCustomizer(serverProperties); + } + + @Bean + @ConditionalOnMissingBean(ReactiveWebServerFactory.class) + TomcatReactiveWebServerFactory tomcatReactiveWebServerFactory( + ObjectProvider connectorCustomizers, + ObjectProvider contextCustomizers, + ObjectProvider> protocolHandlerCustomizers) { + TomcatReactiveWebServerFactory factory = new TomcatReactiveWebServerFactory(); + factory.getConnectorCustomizers().addAll(connectorCustomizers.orderedStream().toList()); + factory.getContextCustomizers().addAll(contextCustomizers.orderedStream().toList()); + factory.getProtocolHandlerCustomizers().addAll(protocolHandlerCustomizers.orderedStream().toList()); + return factory; + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/TomcatReactiveWebServerFactoryCustomizer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/tomcat/TomcatReactiveWebServerFactoryCustomizer.java similarity index 92% rename from spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/TomcatReactiveWebServerFactoryCustomizer.java rename to spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/tomcat/TomcatReactiveWebServerFactoryCustomizer.java index 58ef3a1bd8..98604ec9df 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/TomcatReactiveWebServerFactoryCustomizer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/tomcat/TomcatReactiveWebServerFactoryCustomizer.java @@ -14,15 +14,15 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.web.reactive; +package org.springframework.boot.autoconfigure.web.server.reactive.tomcat; import org.apache.catalina.core.AprLifecycleListener; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.autoconfigure.web.ServerProperties.Tomcat; import org.springframework.boot.autoconfigure.web.ServerProperties.Tomcat.UseApr; -import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.reactive.tomcat.TomcatReactiveWebServerFactory; import org.springframework.util.Assert; /** @@ -30,7 +30,7 @@ import org.springframework.util.Assert; * web servers. * * @author Andy Wilkinson - * @since 2.2.0 + * @since 4.0.0 */ public class TomcatReactiveWebServerFactoryCustomizer implements WebServerFactoryCustomizer { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/tomcat/package-info.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/tomcat/package-info.java new file mode 100644 index 0000000000..efc2014288 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/tomcat/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Classes related to the auto-configuration of a reactive web server using Tomcat. + */ +package org.springframework.boot.autoconfigure.web.server.reactive.tomcat; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/undertow/UndertowReactiveWebServerAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/undertow/UndertowReactiveWebServerAutoConfiguration.java new file mode 100644 index 0000000000..3404a1a93b --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/undertow/UndertowReactiveWebServerAutoConfiguration.java @@ -0,0 +1,58 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.web.server.reactive.undertow; + +import io.undertow.Undertow; + +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.autoconfigure.web.server.reactive.ReactiveWebServerConfiguration; +import org.springframework.boot.autoconfigure.web.server.undertow.UndertowWebServerConfiguration; +import org.springframework.boot.web.server.reactive.ReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.undertow.UndertowReactiveWebServerFactory; +import org.springframework.boot.web.server.undertow.UndertowBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; +import org.springframework.http.ReactiveHttpInputMessage; + +/** + * {@link EnableAutoConfiguration Auto-configuration} for an Undertow-based reactive web + * server. + * + * @author Andy Wilkinson + * @since 4.0.0 + */ +@AutoConfiguration +@ConditionalOnClass({ ReactiveHttpInputMessage.class, Undertow.class }) +@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE) +@Import({ UndertowWebServerConfiguration.class, ReactiveWebServerConfiguration.class }) +public class UndertowReactiveWebServerAutoConfiguration { + + @Bean + @ConditionalOnMissingBean(ReactiveWebServerFactory.class) + UndertowReactiveWebServerFactory undertowReactiveWebServerFactory( + ObjectProvider builderCustomizers) { + UndertowReactiveWebServerFactory factory = new UndertowReactiveWebServerFactory(); + factory.getBuilderCustomizers().addAll(builderCustomizers.orderedStream().toList()); + return factory; + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/undertow/package-info.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/undertow/package-info.java new file mode 100644 index 0000000000..09798d5700 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/reactive/undertow/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Classes related to the auto-configuration of a reactive web server using Undertow. + */ +package org.springframework.boot.autoconfigure.web.server.reactive.undertow; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/ForwardedHeaderFilterCustomizer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/ForwardedHeaderFilterCustomizer.java new file mode 100644 index 0000000000..f26cb48add --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/ForwardedHeaderFilterCustomizer.java @@ -0,0 +1,35 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.web.server.servlet; + +import org.springframework.web.filter.ForwardedHeaderFilter; + +/** + * Customizer for the auto-configured {@link ForwardedHeaderFilter}. + * + * @author Andy Wilkinson + * @since 4.0.0 + */ +public interface ForwardedHeaderFilterCustomizer { + + /** + * Customizes the given {@code filter}. + * @param filter the filter to customize + */ + void customize(ForwardedHeaderFilter filter); + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/ServletWebServerConfiguration.java similarity index 59% rename from spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryAutoConfiguration.java rename to spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/ServletWebServerConfiguration.java index 6b6e955257..6261bd5a20 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/ServletWebServerConfiguration.java @@ -14,10 +14,9 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.web.servlet; +package org.springframework.boot.autoconfigure.web.server.servlet; import jakarta.servlet.DispatcherType; -import jakarta.servlet.ServletRequest; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; @@ -26,22 +25,16 @@ import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigureOrder; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; -import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; -import org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration; import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.autoconfigure.web.servlet.ConditionalOnMissingFilterBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.ssl.SslBundles; import org.springframework.boot.web.server.ErrorPageRegistrarBeanPostProcessor; import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor; +import org.springframework.boot.web.server.servlet.CookieSameSiteSupplier; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.WebListenerRegistrar; -import org.springframework.boot.web.servlet.server.CookieSameSiteSupplier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @@ -52,7 +45,7 @@ import org.springframework.util.ObjectUtils; import org.springframework.web.filter.ForwardedHeaderFilter; /** - * {@link EnableAutoConfiguration Auto-configuration} for servlet web servers. + * {@link Configuration Configuration} for a servlet web server. * * @author Phillip Webb * @author Dave Syer @@ -60,21 +53,15 @@ import org.springframework.web.filter.ForwardedHeaderFilter; * @author Brian Clozel * @author Stephane Nicoll * @author Scott Frederick - * @since 2.0.0 + * @since 4.0.0 */ -@AutoConfiguration(after = SslAutoConfiguration.class) -@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) -@ConditionalOnClass(ServletRequest.class) -@ConditionalOnWebApplication(type = Type.SERVLET) +@Configuration(proxyBeanMethods = false) @EnableConfigurationProperties(ServerProperties.class) -@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class, - ServletWebServerFactoryConfiguration.EmbeddedTomcat.class, - ServletWebServerFactoryConfiguration.EmbeddedJetty.class, - ServletWebServerFactoryConfiguration.EmbeddedUndertow.class }) -public class ServletWebServerFactoryAutoConfiguration { +@Import(ServletWebServerConfiguration.BeanPostProcessorsRegistrar.class) +public class ServletWebServerConfiguration { @Bean - public ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(ServerProperties serverProperties, + ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(ServerProperties serverProperties, ObjectProvider webListenerRegistrars, ObjectProvider cookieSameSiteSuppliers, ObjectProvider sslBundles) { return new ServletWebServerFactoryCustomizer(serverProperties, webListenerRegistrars.orderedStream().toList(), @@ -82,47 +69,23 @@ public class ServletWebServerFactoryAutoConfiguration { } @Bean - @ConditionalOnClass(name = "org.apache.catalina.startup.Tomcat") - public TomcatServletWebServerFactoryCustomizer tomcatServletWebServerFactoryCustomizer( - ServerProperties serverProperties) { - return new TomcatServletWebServerFactoryCustomizer(serverProperties); - } - - @Configuration(proxyBeanMethods = false) @ConditionalOnProperty(name = "server.forward-headers-strategy", havingValue = "framework") @ConditionalOnMissingFilterBean(ForwardedHeaderFilter.class) - static class ForwardedHeaderFilterConfiguration { - - @Bean - @ConditionalOnClass(name = "org.apache.catalina.startup.Tomcat") - ForwardedHeaderFilterCustomizer tomcatForwardedHeaderFilterCustomizer(ServerProperties serverProperties) { - return (filter) -> filter.setRelativeRedirects(serverProperties.getTomcat().isUseRelativeRedirects()); - } - - @Bean - FilterRegistrationBean forwardedHeaderFilter( - ObjectProvider customizerProvider) { - ForwardedHeaderFilter filter = new ForwardedHeaderFilter(); - customizerProvider.ifAvailable((customizer) -> customizer.customize(filter)); - FilterRegistrationBean registration = new FilterRegistrationBean<>(filter); - registration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC, DispatcherType.ERROR); - registration.setOrder(Ordered.HIGHEST_PRECEDENCE); - return registration; - } - - } - - interface ForwardedHeaderFilterCustomizer { - - void customize(ForwardedHeaderFilter filter); - + FilterRegistrationBean forwardedHeaderFilter( + ObjectProvider customizerProvider) { + ForwardedHeaderFilter filter = new ForwardedHeaderFilter(); + customizerProvider.ifAvailable((customizer) -> customizer.customize(filter)); + FilterRegistrationBean registration = new FilterRegistrationBean<>(filter); + registration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC, DispatcherType.ERROR); + registration.setOrder(Ordered.HIGHEST_PRECEDENCE); + return registration; } /** * Registers a {@link WebServerFactoryCustomizerBeanPostProcessor}. Registered via * {@link ImportBeanDefinitionRegistrar} for early registration. */ - public static class BeanPostProcessorsRegistrar implements ImportBeanDefinitionRegistrar, BeanFactoryAware { + static class BeanPostProcessorsRegistrar implements ImportBeanDefinitionRegistrar, BeanFactoryAware { private ConfigurableListableBeanFactory beanFactory; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryCustomizer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/ServletWebServerFactoryCustomizer.java similarity index 88% rename from spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryCustomizer.java rename to spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/ServletWebServerFactoryCustomizer.java index 4952b4d165..02b3ba5b8a 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryCustomizer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/ServletWebServerFactoryCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.web.servlet; +package org.springframework.boot.autoconfigure.web.server.servlet; import java.util.Collections; import java.util.List; @@ -23,9 +23,9 @@ import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.boot.ssl.SslBundles; import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.servlet.ConfigurableServletWebServerFactory; +import org.springframework.boot.web.server.servlet.CookieSameSiteSupplier; import org.springframework.boot.web.servlet.WebListenerRegistrar; -import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; -import org.springframework.boot.web.servlet.server.CookieSameSiteSupplier; import org.springframework.core.Ordered; import org.springframework.util.CollectionUtils; @@ -39,7 +39,7 @@ import org.springframework.util.CollectionUtils; * @author Yunkun Huang * @author Scott Frederick * @author Lasse Wulff - * @since 2.0.0 + * @since 4.0.0 */ public class ServletWebServerFactoryCustomizer implements WebServerFactoryCustomizer, Ordered { @@ -53,15 +53,10 @@ public class ServletWebServerFactoryCustomizer private final SslBundles sslBundles; public ServletWebServerFactoryCustomizer(ServerProperties serverProperties) { - this(serverProperties, Collections.emptyList()); + this(serverProperties, Collections.emptyList(), Collections.emptyList(), null); } public ServletWebServerFactoryCustomizer(ServerProperties serverProperties, - List webListenerRegistrars) { - this(serverProperties, webListenerRegistrars, null, null); - } - - ServletWebServerFactoryCustomizer(ServerProperties serverProperties, List webListenerRegistrars, List cookieSameSiteSuppliers, SslBundles sslBundles) { this.serverProperties = serverProperties; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/servlet/WebSocketServletAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/jetty/JettyServletWebServerAutoConfiguration.java similarity index 51% rename from spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/servlet/WebSocketServletAutoConfiguration.java rename to spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/jetty/JettyServletWebServerAutoConfiguration.java index 71dda5859a..81e4a1437c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/servlet/WebSocketServletAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/jetty/JettyServletWebServerAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,69 +14,59 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.websocket.servlet; +package org.springframework.boot.autoconfigure.web.server.servlet.jetty; import java.util.EnumSet; import jakarta.servlet.DispatcherType; import jakarta.servlet.FilterRegistration.Dynamic; -import jakarta.servlet.Servlet; -import jakarta.websocket.server.ServerContainer; -import org.apache.catalina.startup.Tomcat; -import org.apache.tomcat.websocket.server.WsSci; +import jakarta.servlet.ServletRequest; +import org.eclipse.jetty.ee10.webapp.WebAppContext; import org.eclipse.jetty.ee10.websocket.jakarta.server.config.JakartaWebSocketServletContainerInitializer; import org.eclipse.jetty.ee10.websocket.servlet.WebSocketUpgradeFilter; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.util.Loader; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWarDeployment; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; -import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory; +import org.springframework.boot.autoconfigure.condition.SearchStrategy; +import org.springframework.boot.autoconfigure.web.server.jetty.JettyWebServerConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.ServletWebServerConfiguration; import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.jetty.JettyServerCustomizer; +import org.springframework.boot.web.server.servlet.ServletWebServerFactory; +import org.springframework.boot.web.server.servlet.jetty.JettyServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; /** - * Auto configuration for WebSocket servlet server in embedded Tomcat, Jetty or Undertow. - * Requires the appropriate WebSocket modules to be on the classpath. - *

- * If Tomcat's WebSocket support is detected on the classpath we add a customizer that - * installs the Tomcat WebSocket initializer. In a non-embedded server it should already - * be there. - *

- * If Jetty's WebSocket support is detected on the classpath we add a configuration that - * configures the context with WebSocket support. In a non-embedded server it should - * already be there. - *

- * If Undertow's WebSocket support is detected on the classpath we add a customizer that - * installs the Undertow WebSocket DeploymentInfo Customizer. In a non-embedded server it - * should already be there. + * {@link EnableAutoConfiguration Auto-configuration} for a Jetty-based servlet web + * server. * - * @author Dave Syer - * @author Phillip Webb * @author Andy Wilkinson - * @since 1.0.0 + * @since 4.0.0 */ -@AutoConfiguration(before = ServletWebServerFactoryAutoConfiguration.class) -@ConditionalOnClass({ Servlet.class, ServerContainer.class }) +@AutoConfiguration +@ConditionalOnClass({ ServletRequest.class, Server.class, Loader.class, WebAppContext.class }) @ConditionalOnWebApplication(type = Type.SERVLET) -public class WebSocketServletAutoConfiguration { - - @Configuration(proxyBeanMethods = false) - @ConditionalOnClass({ Tomcat.class, WsSci.class }) - static class TomcatWebSocketConfiguration { - - @Bean - @ConditionalOnMissingBean(name = "websocketServletWebServerCustomizer") - TomcatWebSocketServletWebServerCustomizer websocketServletWebServerCustomizer() { - return new TomcatWebSocketServletWebServerCustomizer(); - } +@Import({ JettyWebServerConfiguration.class, ServletWebServerConfiguration.class }) +public class JettyServletWebServerAutoConfiguration { + @Bean + @ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT) + JettyServletWebServerFactory jettyServletWebServerFactory(ObjectProvider serverCustomizers) { + JettyServletWebServerFactory factory = new JettyServletWebServerFactory(); + factory.getServerCustomizers().addAll(serverCustomizers.orderedStream().toList()); + return factory; } @Configuration(proxyBeanMethods = false) @@ -85,8 +75,8 @@ public class WebSocketServletAutoConfiguration { @Bean @ConditionalOnMissingBean(name = "websocketServletWebServerCustomizer") - JettyWebSocketServletWebServerCustomizer websocketServletWebServerCustomizer() { - return new JettyWebSocketServletWebServerCustomizer(); + WebSocketJettyServletWebServerFactoryCustomizer websocketServletWebServerCustomizer() { + return new WebSocketJettyServletWebServerFactoryCustomizer(); } @Bean @@ -106,16 +96,4 @@ public class WebSocketServletAutoConfiguration { } - @Configuration(proxyBeanMethods = false) - @ConditionalOnClass(io.undertow.websockets.jsr.Bootstrap.class) - static class UndertowWebSocketConfiguration { - - @Bean - @ConditionalOnMissingBean(name = "websocketServletWebServerCustomizer") - UndertowWebSocketServletWebServerCustomizer websocketServletWebServerCustomizer() { - return new UndertowWebSocketServletWebServerCustomizer(); - } - - } - } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/servlet/JettyWebSocketServletWebServerCustomizer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/jetty/WebSocketJettyServletWebServerFactoryCustomizer.java similarity index 89% rename from spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/servlet/JettyWebSocketServletWebServerCustomizer.java rename to spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/jetty/WebSocketJettyServletWebServerFactoryCustomizer.java index ccf0ef8f37..d2d3628a82 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/servlet/JettyWebSocketServletWebServerCustomizer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/jetty/WebSocketJettyServletWebServerFactoryCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.websocket.servlet; +package org.springframework.boot.autoconfigure.web.server.servlet.jetty; import org.eclipse.jetty.ee10.webapp.AbstractConfiguration; import org.eclipse.jetty.ee10.webapp.WebAppContext; @@ -24,8 +24,8 @@ import org.eclipse.jetty.ee10.websocket.servlet.WebSocketUpgradeFilter; import org.eclipse.jetty.websocket.core.server.WebSocketMappings; import org.eclipse.jetty.websocket.core.server.WebSocketServerComponents; -import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.servlet.jetty.JettyServletWebServerFactory; import org.springframework.core.Ordered; /** @@ -34,9 +34,9 @@ import org.springframework.core.Ordered; * @author Dave Syer * @author Phillip Webb * @author Andy Wilkinson - * @since 2.0.0 + * @since 4.0.0 */ -public class JettyWebSocketServletWebServerCustomizer +public class WebSocketJettyServletWebServerFactoryCustomizer implements WebServerFactoryCustomizer, Ordered { @Override diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/jetty/package-info.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/jetty/package-info.java new file mode 100644 index 0000000000..0543e11747 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/jetty/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Classes related to the auto-configuration of a servlet web server using Jetty. + */ +package org.springframework.boot.autoconfigure.web.server.servlet.jetty; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/package-info.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/package-info.java new file mode 100644 index 0000000000..08915aa770 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Classes related to the auto-configuration of a servlet web server. + */ +package org.springframework.boot.autoconfigure.web.server.servlet; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/tomcat/TomcatServletWebServerAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/tomcat/TomcatServletWebServerAutoConfiguration.java new file mode 100644 index 0000000000..da3c212d14 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/tomcat/TomcatServletWebServerAutoConfiguration.java @@ -0,0 +1,81 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.web.server.servlet.tomcat; + +import jakarta.servlet.ServletRequest; +import org.apache.catalina.startup.Tomcat; +import org.apache.coyote.UpgradeProtocol; + +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; +import org.springframework.boot.autoconfigure.condition.SearchStrategy; +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.autoconfigure.web.server.servlet.ForwardedHeaderFilterCustomizer; +import org.springframework.boot.autoconfigure.web.server.servlet.ServletWebServerConfiguration; +import org.springframework.boot.autoconfigure.web.server.tomcat.TomcatWebServerConfiguration; +import org.springframework.boot.web.server.servlet.ServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.tomcat.TomcatConnectorCustomizer; +import org.springframework.boot.web.server.tomcat.TomcatContextCustomizer; +import org.springframework.boot.web.server.tomcat.TomcatProtocolHandlerCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; + +/** + * {@link EnableAutoConfiguration Auto-configuration} for a Tomcat-based servlet web + * server. + * + * @author Andy Wilkinson + * @since 4.0.0 + */ +@AutoConfiguration +@ConditionalOnClass({ ServletRequest.class, Tomcat.class, UpgradeProtocol.class }) +@ConditionalOnWebApplication(type = Type.SERVLET) +@Import({ ServletWebServerConfiguration.class, TomcatWebServerConfiguration.class }) +public class TomcatServletWebServerAutoConfiguration { + + @Bean + @ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT) + TomcatServletWebServerFactory tomcatServletWebServerFactory( + ObjectProvider connectorCustomizers, + ObjectProvider contextCustomizers, + ObjectProvider> protocolHandlerCustomizers) { + TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(); + factory.getConnectorCustomizers().addAll(connectorCustomizers.orderedStream().toList()); + factory.getContextCustomizers().addAll(contextCustomizers.orderedStream().toList()); + factory.getProtocolHandlerCustomizers().addAll(protocolHandlerCustomizers.orderedStream().toList()); + return factory; + } + + @Bean + TomcatServletWebServerFactoryCustomizer tomcatServletWebServerFactoryCustomizer(ServerProperties serverProperties) { + return new TomcatServletWebServerFactoryCustomizer(serverProperties); + } + + @Bean + @ConditionalOnProperty(name = "server.forward-headers-strategy", havingValue = "framework") + ForwardedHeaderFilterCustomizer tomcatForwardedHeaderFilterCustomizer(ServerProperties serverProperties) { + return (filter) -> filter.setRelativeRedirects(serverProperties.getTomcat().isUseRelativeRedirects()); + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/TomcatServletWebServerFactoryCustomizer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/tomcat/TomcatServletWebServerFactoryCustomizer.java similarity index 67% rename from spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/TomcatServletWebServerFactoryCustomizer.java rename to spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/tomcat/TomcatServletWebServerFactoryCustomizer.java index c59ad10c65..8c292a59fe 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/TomcatServletWebServerFactoryCustomizer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/tomcat/TomcatServletWebServerFactoryCustomizer.java @@ -14,17 +14,13 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.web.servlet; - -import org.apache.catalina.core.AprLifecycleListener; +package org.springframework.boot.autoconfigure.web.server.servlet.tomcat; import org.springframework.boot.autoconfigure.web.ServerProperties; -import org.springframework.boot.autoconfigure.web.ServerProperties.Tomcat.UseApr; -import org.springframework.boot.web.embedded.tomcat.ConfigurableTomcatWebServerFactory; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.tomcat.ConfigurableTomcatWebServerFactory; import org.springframework.core.Ordered; -import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; /** @@ -33,14 +29,13 @@ import org.springframework.util.ObjectUtils; * * @author Brian Clozel * @author Phillip Webb - * @since 2.0.0 */ -public class TomcatServletWebServerFactoryCustomizer +class TomcatServletWebServerFactoryCustomizer implements WebServerFactoryCustomizer, Ordered { private final ServerProperties serverProperties; - public TomcatServletWebServerFactoryCustomizer(ServerProperties serverProperties) { + TomcatServletWebServerFactoryCustomizer(ServerProperties serverProperties) { this.serverProperties = serverProperties; } @@ -60,7 +55,6 @@ public class TomcatServletWebServerFactoryCustomizer } customizeUseRelativeRedirects(factory, tomcatProperties.isUseRelativeRedirects()); factory.setDisableMBeanRegistry(!tomcatProperties.getMbeanregistry().isEnabled()); - factory.setUseApr(getUseApr(tomcatProperties.getUseApr())); } private void customizeRedirectContextRoot(ConfigurableTomcatWebServerFactory factory, boolean redirectContextRoot) { @@ -72,22 +66,4 @@ public class TomcatServletWebServerFactoryCustomizer factory.addContextCustomizers((context) -> context.setUseRelativeRedirects(useRelativeRedirects)); } - private boolean getUseApr(UseApr useApr) { - return switch (useApr) { - case ALWAYS -> { - Assert.state(isAprAvailable(), "APR has been configured to 'ALWAYS', but it's not available"); - yield true; - } - case WHEN_AVAILABLE -> isAprAvailable(); - case NEVER -> false; - }; - } - - private boolean isAprAvailable() { - // At least one instance of AprLifecycleListener has to be created for - // isAprAvailable() to work - new AprLifecycleListener(); - return AprLifecycleListener.isAprAvailable(); - } - } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/tomcat/package-info.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/tomcat/package-info.java new file mode 100644 index 0000000000..a6c208b531 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/tomcat/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Classes related to the auto-configuration of a servlet web server using Tomcat. + */ +package org.springframework.boot.autoconfigure.web.server.servlet.tomcat; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/undertow/UndertowServletWebServerAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/undertow/UndertowServletWebServerAutoConfiguration.java new file mode 100644 index 0000000000..8e78e4176f --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/undertow/UndertowServletWebServerAutoConfiguration.java @@ -0,0 +1,85 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.web.server.servlet.undertow; + +import io.undertow.Undertow; +import io.undertow.websockets.jsr.Bootstrap; +import jakarta.servlet.ServletRequest; +import org.xnio.SslClientAuthMode; + +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; +import org.springframework.boot.autoconfigure.condition.SearchStrategy; +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.autoconfigure.web.server.servlet.ServletWebServerConfiguration; +import org.springframework.boot.autoconfigure.web.server.undertow.UndertowWebServerConfiguration; +import org.springframework.boot.web.server.servlet.ServletWebServerFactory; +import org.springframework.boot.web.server.servlet.undertow.UndertowDeploymentInfoCustomizer; +import org.springframework.boot.web.server.servlet.undertow.UndertowServletWebServerFactory; +import org.springframework.boot.web.server.undertow.UndertowBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +/** + * {@link EnableAutoConfiguration Auto-configuration} for an Undertow-based servlet web + * server. + * + * @author Andy Wilkinson + * @since 4.0.0 + */ +@AutoConfiguration +@ConditionalOnClass({ ServletRequest.class, Undertow.class, SslClientAuthMode.class }) +@ConditionalOnWebApplication(type = Type.SERVLET) +@Import({ UndertowWebServerConfiguration.class, ServletWebServerConfiguration.class }) +public class UndertowServletWebServerAutoConfiguration { + + @Bean + @ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT) + UndertowServletWebServerFactory undertowServletWebServerFactory( + ObjectProvider deploymentInfoCustomizers, + ObjectProvider builderCustomizers) { + UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory(); + factory.getDeploymentInfoCustomizers().addAll(deploymentInfoCustomizers.orderedStream().toList()); + factory.getBuilderCustomizers().addAll(builderCustomizers.orderedStream().toList()); + return factory; + } + + @Bean + UndertowServletWebServerFactoryCustomizer undertowServletWebServerFactoryCustomizer( + ServerProperties serverProperties) { + return new UndertowServletWebServerFactoryCustomizer(serverProperties); + } + + @Configuration(proxyBeanMethods = false) + @ConditionalOnClass(Bootstrap.class) + static class UndertowWebSocketConfiguration { + + @Bean + @ConditionalOnMissingBean(name = "websocketServletWebServerCustomizer") + WebSocketUndertowServletWebServerFactoryCustomizer websocketServletWebServerCustomizer() { + return new WebSocketUndertowServletWebServerFactoryCustomizer(); + } + + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/UndertowServletWebServerFactoryCustomizer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/undertow/UndertowServletWebServerFactoryCustomizer.java similarity index 73% rename from spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/UndertowServletWebServerFactoryCustomizer.java rename to spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/undertow/UndertowServletWebServerFactoryCustomizer.java index b87b702bfd..2f2c4a0ce9 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/UndertowServletWebServerFactoryCustomizer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/undertow/UndertowServletWebServerFactoryCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,25 +14,23 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.web.servlet; +package org.springframework.boot.autoconfigure.web.server.servlet.undertow; import org.springframework.boot.autoconfigure.web.ServerProperties; -import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.servlet.undertow.UndertowServletWebServerFactory; /** * {@link WebServerFactoryCustomizer} to apply {@link ServerProperties} to Undertow * Servlet web servers. * * @author Andy Wilkinson - * @since 2.1.7 */ -public class UndertowServletWebServerFactoryCustomizer - implements WebServerFactoryCustomizer { +class UndertowServletWebServerFactoryCustomizer implements WebServerFactoryCustomizer { private final ServerProperties serverProperties; - public UndertowServletWebServerFactoryCustomizer(ServerProperties serverProperties) { + UndertowServletWebServerFactoryCustomizer(ServerProperties serverProperties) { this.serverProperties = serverProperties; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/servlet/UndertowWebSocketServletWebServerCustomizer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/undertow/WebSocketUndertowServletWebServerFactoryCustomizer.java similarity index 80% rename from spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/servlet/UndertowWebSocketServletWebServerCustomizer.java rename to spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/undertow/WebSocketUndertowServletWebServerFactoryCustomizer.java index d9826385d7..3df409895d 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/servlet/UndertowWebSocketServletWebServerCustomizer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/undertow/WebSocketUndertowServletWebServerFactoryCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,14 +14,14 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.websocket.servlet; +package org.springframework.boot.autoconfigure.web.server.servlet.undertow; import io.undertow.servlet.api.DeploymentInfo; import io.undertow.websockets.jsr.WebSocketDeploymentInfo; -import org.springframework.boot.web.embedded.undertow.UndertowDeploymentInfoCustomizer; -import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.servlet.undertow.UndertowDeploymentInfoCustomizer; +import org.springframework.boot.web.server.servlet.undertow.UndertowServletWebServerFactory; import org.springframework.core.Ordered; /** @@ -30,7 +30,7 @@ import org.springframework.core.Ordered; * @author Phillip Webb * @since 2.0.0 */ -public class UndertowWebSocketServletWebServerCustomizer +public class WebSocketUndertowServletWebServerFactoryCustomizer implements WebServerFactoryCustomizer, Ordered { @Override diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/undertow/package-info.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/undertow/package-info.java new file mode 100644 index 0000000000..b35799adef --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/servlet/undertow/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Classes related to the auto-configuration of a servlet web server using Undertow. + */ +package org.springframework.boot.autoconfigure.web.server.servlet.undertow; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/TomcatVirtualThreadsWebServerFactoryCustomizer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/tomcat/TomcatVirtualThreadsWebServerFactoryCustomizer.java similarity index 86% rename from spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/TomcatVirtualThreadsWebServerFactoryCustomizer.java rename to spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/tomcat/TomcatVirtualThreadsWebServerFactoryCustomizer.java index 54ba36c7e6..abef8ea53a 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/TomcatVirtualThreadsWebServerFactoryCustomizer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/tomcat/TomcatVirtualThreadsWebServerFactoryCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,13 +14,13 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.web.embedded; +package org.springframework.boot.autoconfigure.web.server.tomcat; import org.apache.coyote.ProtocolHandler; import org.apache.tomcat.util.threads.VirtualThreadExecutor; -import org.springframework.boot.web.embedded.tomcat.ConfigurableTomcatWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.tomcat.ConfigurableTomcatWebServerFactory; import org.springframework.core.Ordered; /** @@ -28,7 +28,7 @@ import org.springframework.core.Ordered; * handler}. * * @author Moritz Halbritter - * @since 3.2.0 + * @since 4.0.0 */ public class TomcatVirtualThreadsWebServerFactoryCustomizer implements WebServerFactoryCustomizer, Ordered { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/tomcat/TomcatWebServerConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/tomcat/TomcatWebServerConfiguration.java new file mode 100644 index 0000000000..50098f05f8 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/tomcat/TomcatWebServerConfiguration.java @@ -0,0 +1,67 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.web.server.tomcat; + +import org.apache.tomcat.websocket.server.WsSci; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWarDeployment; +import org.springframework.boot.autoconfigure.condition.ConditionalOnThreading; +import org.springframework.boot.autoconfigure.thread.Threading; +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.autoconfigure.web.server.reactive.tomcat.TomcatReactiveWebServerAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +/** + * {@link Configuration Configuration} for a Tomcat-based reactive or servlet web server. + * + * @author Andy Wilkinson + * @since 4.0.0 + * @see TomcatReactiveWebServerAutoConfiguration + * @see TomcatServletWebServerAutoConfiguration + */ +@ConditionalOnNotWarDeployment +@Configuration(proxyBeanMethods = false) +public class TomcatWebServerConfiguration { + + @Bean + TomcatWebServerFactoryCustomizer tomcatWebServerFactoryCustomizer(Environment environment, + ServerProperties serverProperties) { + return new TomcatWebServerFactoryCustomizer(environment, serverProperties); + } + + @Bean + @ConditionalOnThreading(Threading.VIRTUAL) + TomcatVirtualThreadsWebServerFactoryCustomizer tomcatVirtualThreadsProtocolHandlerCustomizer() { + return new TomcatVirtualThreadsWebServerFactoryCustomizer(); + } + + @Configuration(proxyBeanMethods = false) + @ConditionalOnClass(WsSci.class) + static class TomcatWebSocketConfiguration { + + @Bean + WebSocketTomcatWebServerFactoryCustomizer webSocketWebServerCustomizer() { + return new WebSocketTomcatWebServerFactoryCustomizer(); + } + + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/tomcat/TomcatWebServerFactoryCustomizer.java similarity index 93% rename from spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizer.java rename to spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/tomcat/TomcatWebServerFactoryCustomizer.java index c60ce2cffe..6bb5ffbde7 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/tomcat/TomcatWebServerFactoryCustomizer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.web.embedded; +package org.springframework.boot.autoconfigure.web.server.tomcat; import java.time.Duration; import java.util.List; @@ -22,6 +22,7 @@ import java.util.function.ObjIntConsumer; import java.util.stream.Collectors; import org.apache.catalina.Lifecycle; +import org.apache.catalina.core.AprLifecycleListener; import org.apache.catalina.valves.AccessLogValve; import org.apache.catalina.valves.ErrorReportValve; import org.apache.catalina.valves.RemoteIpValve; @@ -36,18 +37,19 @@ import org.springframework.boot.autoconfigure.web.ErrorProperties.IncludeAttribu import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.autoconfigure.web.ServerProperties.Tomcat.Accesslog; import org.springframework.boot.autoconfigure.web.ServerProperties.Tomcat.Remoteip; +import org.springframework.boot.autoconfigure.web.ServerProperties.Tomcat.UseApr; import org.springframework.boot.cloud.CloudPlatform; import org.springframework.boot.context.properties.PropertyMapper; -import org.springframework.boot.web.embedded.tomcat.ConfigurableTomcatWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.tomcat.ConfigurableTomcatWebServerFactory; import org.springframework.core.Ordered; import org.springframework.core.env.Environment; +import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.springframework.util.unit.DataSize; /** - * Customization for Tomcat-specific features common for both Servlet and Reactive - * servers. + * Customization for Tomcat-specific features common to both Servlet and Reactive servers. * * @author Brian Clozel * @author Yulin Qin @@ -62,7 +64,7 @@ import org.springframework.util.unit.DataSize; * @author Parviz Rozikov * @author Florian Storz * @author Michael Weidmann - * @since 2.0.0 + * @since 4.0.0 */ public class TomcatWebServerFactoryCustomizer implements WebServerFactoryCustomizer, Ordered { @@ -149,6 +151,25 @@ public class TomcatWebServerFactoryCustomizer .to((relaxedChars) -> customizeRelaxedQueryChars(factory, relaxedChars)); customizeStaticResources(factory); customizeErrorReportValve(this.serverProperties.getError(), factory); + factory.setUseApr(getUseApr(this.serverProperties.getTomcat().getUseApr())); + } + + private boolean getUseApr(UseApr useApr) { + return switch (useApr) { + case ALWAYS -> { + Assert.state(isAprAvailable(), "APR has been configured to 'ALWAYS', but it's not available"); + yield true; + } + case WHEN_AVAILABLE -> isAprAvailable(); + case NEVER -> false; + }; + } + + private boolean isAprAvailable() { + // At least one instance of AprLifecycleListener has to be created for + // isAprAvailable() to work + new AprLifecycleListener(); + return AprLifecycleListener.isAprAvailable(); } private boolean isPositive(int value) { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/servlet/TomcatWebSocketServletWebServerCustomizer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/tomcat/WebSocketTomcatWebServerFactoryCustomizer.java similarity index 57% rename from spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/servlet/TomcatWebSocketServletWebServerCustomizer.java rename to spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/tomcat/WebSocketTomcatWebServerFactoryCustomizer.java index e390b5bf2d..46680b91cc 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/servlet/TomcatWebSocketServletWebServerCustomizer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/tomcat/WebSocketTomcatWebServerFactoryCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,33 +14,25 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.websocket.servlet; +package org.springframework.boot.autoconfigure.web.server.tomcat; import org.apache.tomcat.websocket.server.WsSci; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; -import org.springframework.core.Ordered; +import org.springframework.boot.web.server.tomcat.ConfigurableTomcatWebServerFactory; /** - * WebSocket customizer for {@link TomcatServletWebServerFactory}. + * {@link WebServerFactoryCustomizer} that configures Tomcat's WebSocket support. * - * @author Dave Syer - * @author Phillip Webb * @author Andy Wilkinson - * @since 2.0.0 + * @since 4.0.0 */ -public class TomcatWebSocketServletWebServerCustomizer - implements WebServerFactoryCustomizer, Ordered { +public class WebSocketTomcatWebServerFactoryCustomizer + implements WebServerFactoryCustomizer { @Override - public void customize(TomcatServletWebServerFactory factory) { + public void customize(ConfigurableTomcatWebServerFactory factory) { factory.addContextCustomizers((context) -> context.addServletContainerInitializer(new WsSci(), null)); } - @Override - public int getOrder() { - return 0; - } - } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/tomcat/package-info.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/tomcat/package-info.java new file mode 100644 index 0000000000..b3ba789bd1 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/tomcat/package-info.java @@ -0,0 +1,21 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Classes related to the auto-configuration of a servlet or reactive web server using + * Tomcat. + */ +package org.springframework.boot.autoconfigure.web.server.tomcat; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/undertow/UndertowWebServerConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/undertow/UndertowWebServerConfiguration.java new file mode 100644 index 0000000000..a78bbb14d9 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/undertow/UndertowWebServerConfiguration.java @@ -0,0 +1,52 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.web.server.undertow; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWarDeployment; +import org.springframework.boot.autoconfigure.condition.ConditionalOnThreading; +import org.springframework.boot.autoconfigure.thread.Threading; +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.web.server.servlet.undertow.UndertowDeploymentInfoCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; +import org.springframework.core.task.VirtualThreadTaskExecutor; + +/** + * {@link Configuration Configuration} for an Undertow-based reactive or servlet web + * server. + * + * @author Andy Wilkinson + * @since 4.0.0 + */ +@ConditionalOnNotWarDeployment +@Configuration(proxyBeanMethods = false) +public class UndertowWebServerConfiguration { + + @Bean + UndertowWebServerFactoryCustomizer undertowWebServerFactoryCustomizer(Environment environment, + ServerProperties serverProperties) { + return new UndertowWebServerFactoryCustomizer(environment, serverProperties); + } + + @Bean + @ConditionalOnThreading(Threading.VIRTUAL) + UndertowDeploymentInfoCustomizer virtualThreadsUndertowDeploymentInfoCustomizer() { + return (deploymentInfo) -> deploymentInfo.setExecutor(new VirtualThreadTaskExecutor("undertow-")); + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/UndertowWebServerFactoryCustomizer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/undertow/UndertowWebServerFactoryCustomizer.java similarity index 97% rename from spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/UndertowWebServerFactoryCustomizer.java rename to spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/undertow/UndertowWebServerFactoryCustomizer.java index c71f67929f..716ef1b7dd 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/UndertowWebServerFactoryCustomizer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/undertow/UndertowWebServerFactoryCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.web.embedded; +package org.springframework.boot.autoconfigure.web.server.undertow; import java.lang.reflect.Modifier; import java.nio.charset.Charset; @@ -34,8 +34,8 @@ import org.springframework.boot.autoconfigure.web.ServerProperties.Undertow; import org.springframework.boot.autoconfigure.web.ServerProperties.Undertow.Accesslog; import org.springframework.boot.cloud.CloudPlatform; import org.springframework.boot.context.properties.PropertyMapper; -import org.springframework.boot.web.embedded.undertow.ConfigurableUndertowWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.undertow.ConfigurableUndertowWebServerFactory; import org.springframework.core.Ordered; import org.springframework.core.env.Environment; import org.springframework.util.Assert; @@ -54,7 +54,7 @@ import org.springframework.util.unit.DataSize; * @author Arstiom Yudovin * @author Rafiullah Hamedy * @author HaiTao Zhang - * @since 2.0.0 + * @since 4.0.0 */ public class UndertowWebServerFactoryCustomizer implements WebServerFactoryCustomizer, Ordered { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/undertow/package-info.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/undertow/package-info.java new file mode 100644 index 0000000000..6c0d44dfbe --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/server/undertow/package-info.java @@ -0,0 +1,21 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Classes related to the auto-configuration of a servlet or reactive web server using + * Undertow. + */ +package org.springframework.boot.autoconfigure.web.server.undertow; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/DispatcherServletAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/DispatcherServletAutoConfiguration.java index e32f25072d..fed634be05 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/DispatcherServletAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/DispatcherServletAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -63,7 +63,7 @@ import org.springframework.web.servlet.DispatcherServlet; * @since 2.0.0 */ @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) -@AutoConfiguration(after = ServletWebServerFactoryAutoConfiguration.class) +@AutoConfiguration @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass(DispatcherServlet.class) public class DispatcherServletAutoConfiguration { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryConfiguration.java deleted file mode 100644 index 266b298eeb..0000000000 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryConfiguration.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2012-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.autoconfigure.web.servlet; - -import io.undertow.Undertow; -import jakarta.servlet.Servlet; -import org.apache.catalina.startup.Tomcat; -import org.apache.coyote.UpgradeProtocol; -import org.eclipse.jetty.ee10.webapp.WebAppContext; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.util.Loader; -import org.xnio.SslClientAuthMode; - -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.SearchStrategy; -import org.springframework.boot.autoconfigure.web.ServerProperties; -import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer; -import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory; -import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer; -import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer; -import org.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; -import org.springframework.boot.web.embedded.undertow.UndertowBuilderCustomizer; -import org.springframework.boot.web.embedded.undertow.UndertowDeploymentInfoCustomizer; -import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory; -import org.springframework.boot.web.servlet.server.ServletWebServerFactory; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * Configuration classes for servlet web servers - *

- * Those should be {@code @Import} in a regular auto-configuration class to guarantee - * their order of execution. - * - * @author Phillip Webb - * @author Dave Syer - * @author Ivan Sopov - * @author Brian Clozel - * @author Stephane Nicoll - * @author Raheela Asalm - * @author Sergey Serdyuk - */ -@Configuration(proxyBeanMethods = false) -class ServletWebServerFactoryConfiguration { - - @Configuration(proxyBeanMethods = false) - @ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class }) - @ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT) - static class EmbeddedTomcat { - - @Bean - TomcatServletWebServerFactory tomcatServletWebServerFactory( - ObjectProvider connectorCustomizers, - ObjectProvider contextCustomizers, - ObjectProvider> protocolHandlerCustomizers) { - TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(); - factory.getTomcatConnectorCustomizers().addAll(connectorCustomizers.orderedStream().toList()); - factory.getTomcatContextCustomizers().addAll(contextCustomizers.orderedStream().toList()); - factory.getTomcatProtocolHandlerCustomizers().addAll(protocolHandlerCustomizers.orderedStream().toList()); - return factory; - } - - } - - /** - * Nested configuration if Jetty is being used. - */ - @Configuration(proxyBeanMethods = false) - @ConditionalOnClass({ Servlet.class, Server.class, Loader.class, WebAppContext.class }) - @ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT) - static class EmbeddedJetty { - - @Bean - JettyServletWebServerFactory jettyServletWebServerFactory( - ObjectProvider serverCustomizers) { - JettyServletWebServerFactory factory = new JettyServletWebServerFactory(); - factory.getServerCustomizers().addAll(serverCustomizers.orderedStream().toList()); - return factory; - } - - } - - /** - * Nested configuration if Undertow is being used. - */ - @Configuration(proxyBeanMethods = false) - @ConditionalOnClass({ Servlet.class, Undertow.class, SslClientAuthMode.class }) - @ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT) - static class EmbeddedUndertow { - - @Bean - UndertowServletWebServerFactory undertowServletWebServerFactory( - ObjectProvider deploymentInfoCustomizers, - ObjectProvider builderCustomizers) { - UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory(); - factory.getDeploymentInfoCustomizers().addAll(deploymentInfoCustomizers.orderedStream().toList()); - factory.getBuilderCustomizers().addAll(builderCustomizers.orderedStream().toList()); - return factory; - } - - @Bean - UndertowServletWebServerFactoryCustomizer undertowServletWebServerFactoryCustomizer( - ServerProperties serverProperties) { - return new UndertowServletWebServerFactoryCustomizer(serverProperties); - } - - } - -} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/error/BasicErrorController.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/error/BasicErrorController.java index 4a082f2ec3..e5a241338e 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/error/BasicErrorController.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/error/BasicErrorController.java @@ -26,8 +26,8 @@ import jakarta.servlet.http.HttpServletResponse; import org.springframework.boot.autoconfigure.web.ErrorProperties; import org.springframework.boot.web.error.ErrorAttributeOptions; import org.springframework.boot.web.error.ErrorAttributeOptions.Include; +import org.springframework.boot.web.server.servlet.ConfigurableServletWebServerFactory; import org.springframework.boot.web.servlet.error.ErrorAttributes; -import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactory; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; @@ -42,7 +42,7 @@ import org.springframework.web.servlet.ModelAndView; * Basic global error {@link Controller @Controller}, rendering {@link ErrorAttributes}. * More specific errors can be handled either using Spring MVC abstractions (e.g. * {@code @ExceptionHandler}) or by adding servlet - * {@link AbstractServletWebServerFactory#setErrorPages server error pages}. + * {@link ConfigurableServletWebServerFactory#setErrorPages server error pages}. * * @author Dave Syer * @author Phillip Webb diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/webservices/WebServicesAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/webservices/WebServicesAutoConfiguration.java index bed9af37da..c38e63384a 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/webservices/WebServicesAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/webservices/WebServicesAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,7 +33,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.bind.Bindable; import org.springframework.boot.context.properties.bind.Binder; @@ -59,7 +58,7 @@ import org.springframework.xml.xsd.SimpleXsdSchema; * @author Stephane Nicoll * @since 1.4.0 */ -@AutoConfiguration(after = ServletWebServerFactoryAutoConfiguration.class) +@AutoConfiguration @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass(MessageDispatcherServlet.class) @ConditionalOnMissingBean(WsConfigurationSupport.class) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/reactive/TomcatWebSocketReactiveWebServerCustomizer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/reactive/TomcatWebSocketReactiveWebServerCustomizer.java deleted file mode 100644 index 9bac4168f2..0000000000 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/reactive/TomcatWebSocketReactiveWebServerCustomizer.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2012-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.autoconfigure.websocket.reactive; - -import org.apache.tomcat.websocket.server.WsSci; - -import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory; -import org.springframework.boot.web.server.WebServerFactoryCustomizer; -import org.springframework.core.Ordered; - -/** - * WebSocket customizer for {@link TomcatReactiveWebServerFactory}. - * - * @author Brian Clozel - * @since 2.0.0 - */ -public class TomcatWebSocketReactiveWebServerCustomizer - implements WebServerFactoryCustomizer, Ordered { - - @Override - public void customize(TomcatReactiveWebServerFactory factory) { - factory.addContextCustomizers((context) -> context.addServletContainerInitializer(new WsSci(), null)); - } - - @Override - public int getOrder() { - return 0; - } - -} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/reactive/WebSocketReactiveAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/reactive/WebSocketReactiveAutoConfiguration.java deleted file mode 100644 index 3592ba14b3..0000000000 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/reactive/WebSocketReactiveAutoConfiguration.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2012-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.autoconfigure.websocket.reactive; - -import jakarta.servlet.Servlet; -import jakarta.websocket.server.ServerContainer; -import org.apache.catalina.startup.Tomcat; -import org.apache.tomcat.websocket.server.WsSci; -import org.eclipse.jetty.ee10.websocket.jakarta.server.config.JakartaWebSocketServletContainerInitializer; - -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; -import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; -import org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * Auto-configuration for WebSocket reactive server in Tomcat, Jetty or Undertow. Requires - * the appropriate WebSocket modules to be on the classpath. - *

- * If Tomcat's WebSocket support is detected on the classpath we add a customizer that - * installs the Tomcat WebSocket initializer. - * - * @author Brian Clozel - * @since 2.0.0 - */ -@AutoConfiguration(before = ReactiveWebServerFactoryAutoConfiguration.class) -@ConditionalOnClass({ Servlet.class, ServerContainer.class }) -@ConditionalOnWebApplication(type = Type.REACTIVE) -public class WebSocketReactiveAutoConfiguration { - - @Configuration(proxyBeanMethods = false) - @ConditionalOnClass({ Tomcat.class, WsSci.class }) - static class TomcatWebSocketConfiguration { - - @Bean - @ConditionalOnMissingBean(name = "websocketReactiveWebServerCustomizer") - TomcatWebSocketReactiveWebServerCustomizer websocketReactiveWebServerCustomizer() { - return new TomcatWebSocketReactiveWebServerCustomizer(); - } - - } - - @Configuration(proxyBeanMethods = false) - @ConditionalOnClass(JakartaWebSocketServletContainerInitializer.class) - static class JettyWebSocketConfiguration { - - @Bean - @ConditionalOnMissingBean(name = "websocketReactiveWebServerCustomizer") - JettyWebSocketReactiveWebServerCustomizer websocketServletWebServerCustomizer() { - return new JettyWebSocketReactiveWebServerCustomizer(); - } - - } - -} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index a691e4bbf4..7a2fba2462 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -136,23 +136,26 @@ org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration -org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration org.springframework.boot.autoconfigure.web.reactive.ReactiveMultipartAutoConfiguration -org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration org.springframework.boot.autoconfigure.web.reactive.WebSessionIdResolverAutoConfiguration org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration +org.springframework.boot.autoconfigure.web.server.reactive.jetty.JettyReactiveWebServerAutoConfiguration +org.springframework.boot.autoconfigure.web.server.reactive.netty.NettyReactiveWebServerAutoConfiguration +org.springframework.boot.autoconfigure.web.server.reactive.tomcat.TomcatReactiveWebServerAutoConfiguration +org.springframework.boot.autoconfigure.web.server.reactive.undertow.UndertowReactiveWebServerAutoConfiguration +org.springframework.boot.autoconfigure.web.server.servlet.jetty.JettyServletWebServerAutoConfiguration +org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration +org.springframework.boot.autoconfigure.web.server.servlet.undertow.UndertowServletWebServerAutoConfiguration org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration -org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration -org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration -org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration +org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/admin/SpringApplicationAdminJmxAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/admin/SpringApplicationAdminJmxAutoConfigurationTests.java index 3e08cc6530..9bc76c4658 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/admin/SpringApplicationAdminJmxAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/admin/SpringApplicationAdminJmxAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,8 +31,8 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.boot.WebApplicationType; import org.springframework.boot.admin.SpringApplicationAdminMXBeanRegistrar; import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext; @@ -111,7 +111,7 @@ class SpringApplicationAdminJmxAutoConfigurationTests { @Test void registerWithSimpleWebApp() throws Exception { try (ConfigurableApplicationContext context = new SpringApplicationBuilder() - .sources(ServletWebServerFactoryAutoConfiguration.class, DispatcherServletAutoConfiguration.class, + .sources(TomcatServletWebServerAutoConfiguration.class, DispatcherServletAutoConfiguration.class, MultipleMBeanExportersConfiguration.class, SpringApplicationAdminJmxAutoConfiguration.class) .run("--" + ENABLE_ADMIN_PROP, "--server.port=0")) { assertThat(context).isInstanceOf(ServletWebServerApplicationContext.class); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnNotWebApplicationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnNotWebApplicationTests.java index 75c03bc0ba..ee9ab79a99 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnNotWebApplicationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnNotWebApplicationTests.java @@ -22,8 +22,8 @@ import reactor.core.publisher.Mono; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; -import org.springframework.boot.web.reactive.server.MockReactiveWebServerFactory; -import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.MockReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.ReactiveWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.server.reactive.HttpHandler; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnWebApplicationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnWebApplicationTests.java index 1ad6959d8d..45ef33babd 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnWebApplicationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnWebApplicationTests.java @@ -22,8 +22,8 @@ import reactor.core.publisher.Mono; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebApplicationContext; -import org.springframework.boot.web.reactive.server.MockReactiveWebServerFactory; -import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.MockReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.ReactiveWebServerFactory; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebApplicationContext; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/graphql/rsocket/GraphQlRSocketAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/graphql/rsocket/GraphQlRSocketAutoConfigurationTests.java index bdf39ff98b..a48d3200d1 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/graphql/rsocket/GraphQlRSocketAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/graphql/rsocket/GraphQlRSocketAutoConfigurationTests.java @@ -38,9 +38,9 @@ import org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContex import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; import org.springframework.boot.testsupport.classpath.resources.WithResource; import org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer; -import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; -import org.springframework.boot.web.embedded.netty.NettyRouteProvider; import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext; +import org.springframework.boot.web.server.reactive.netty.NettyReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.netty.NettyRouteProvider; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.graphql.client.RSocketGraphQlClient; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/h2/H2ConsoleAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/h2/H2ConsoleAutoConfigurationTests.java index 85dcdaa283..19aec6ef9d 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/h2/H2ConsoleAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/h2/H2ConsoleAutoConfigurationTests.java @@ -30,7 +30,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.BeanCreationException; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.context.properties.ConfigurationPropertiesBindException; import org.springframework.boot.context.properties.bind.BindException; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; @@ -185,7 +185,7 @@ class H2ConsoleAutoConfigurationTests { void dataSourceIsNotInitializedEarly(CapturedOutput output) { new WebApplicationContextRunner(AnnotationConfigServletWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(H2ConsoleAutoConfiguration.class, - ServletWebServerFactoryAutoConfiguration.class)) + TomcatServletWebServerAutoConfiguration.class)) .withUserConfiguration(EarlyInitializationConfiguration.class) .withPropertyValues("spring.h2.console.enabled=true", "server.port=0") .run((context) -> { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomApplicationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomApplicationTests.java index 387c70281f..90e9f8122d 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomApplicationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomApplicationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,7 +25,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; @@ -72,7 +72,7 @@ class JerseyAutoConfigurationCustomApplicationTests { } @Configuration(proxyBeanMethods = false) - @Import({ ServletWebServerFactoryAutoConfiguration.class, JerseyAutoConfiguration.class, + @Import({ TomcatServletWebServerAutoConfiguration.class, JerseyAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class }) static class TestConfiguration { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomFilterContextPathTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomFilterContextPathTests.java index 869beead28..e50a37697a 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomFilterContextPathTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomFilterContextPathTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,7 +32,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; @@ -91,7 +91,7 @@ class JerseyAutoConfigurationCustomFilterContextPathTests { @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration - @Import({ ServletWebServerFactoryAutoConfiguration.class, JerseyAutoConfiguration.class, + @Import({ TomcatServletWebServerAutoConfiguration.class, JerseyAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class }) protected @interface MinimalWebConfiguration { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomFilterPathTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomFilterPathTests.java index cd40136bf3..2d789c3e18 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomFilterPathTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomFilterPathTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,7 +32,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; @@ -90,7 +90,7 @@ class JerseyAutoConfigurationCustomFilterPathTests { @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration - @Import({ ServletWebServerFactoryAutoConfiguration.class, JerseyAutoConfiguration.class, + @Import({ TomcatServletWebServerAutoConfiguration.class, JerseyAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class }) protected @interface MinimalWebConfiguration { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomLoadOnStartupTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomLoadOnStartupTests.java index b35725de0f..b8f6452c38 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomLoadOnStartupTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomLoadOnStartupTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,7 +27,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.context.ApplicationContext; @@ -67,7 +67,7 @@ class JerseyAutoConfigurationCustomLoadOnStartupTests { @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration - @Import({ ServletWebServerFactoryAutoConfiguration.class, JerseyAutoConfiguration.class, + @Import({ JerseyAutoConfiguration.class, TomcatServletWebServerAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class }) protected @interface MinimalWebConfiguration { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomObjectMapperProviderTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomObjectMapperProviderTests.java index fe823f0954..af06c5b1da 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomObjectMapperProviderTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomObjectMapperProviderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,7 +32,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; @@ -117,7 +117,7 @@ class JerseyAutoConfigurationCustomObjectMapperProviderTests { @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration - @Import({ ServletWebServerFactoryAutoConfiguration.class, JacksonAutoConfiguration.class, + @Import({ TomcatServletWebServerAutoConfiguration.class, JacksonAutoConfiguration.class, JerseyAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class }) protected @interface MinimalWebConfiguration { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomServletContextPathTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomServletContextPathTests.java index 65a806fd51..ab3bbed3f5 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomServletContextPathTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomServletContextPathTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,7 +32,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; @@ -89,7 +89,7 @@ class JerseyAutoConfigurationCustomServletContextPathTests { @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration - @Import({ ServletWebServerFactoryAutoConfiguration.class, JerseyAutoConfiguration.class, + @Import({ TomcatServletWebServerAutoConfiguration.class, JerseyAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class }) protected @interface MinimalWebConfiguration { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomServletPathTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomServletPathTests.java index 46cd436bb7..372601d55a 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomServletPathTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationCustomServletPathTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,7 +32,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; @@ -89,7 +89,7 @@ class JerseyAutoConfigurationCustomServletPathTests { @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration - @Import({ ServletWebServerFactoryAutoConfiguration.class, JerseyAutoConfiguration.class, + @Import({ TomcatServletWebServerAutoConfiguration.class, JerseyAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class }) protected @interface MinimalWebConfiguration { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationDefaultFilterPathTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationDefaultFilterPathTests.java index 085cb5df26..c9bb1dbf09 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationDefaultFilterPathTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationDefaultFilterPathTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,7 +31,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; @@ -88,7 +88,7 @@ class JerseyAutoConfigurationDefaultFilterPathTests { @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration - @Import({ ServletWebServerFactoryAutoConfiguration.class, JerseyAutoConfiguration.class, + @Import({ TomcatServletWebServerAutoConfiguration.class, JerseyAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class }) protected @interface MinimalWebConfiguration { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationDefaultServletPathTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationDefaultServletPathTests.java index 359f67433c..3ba9bc0448 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationDefaultServletPathTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationDefaultServletPathTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,7 +31,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; @@ -87,7 +87,7 @@ class JerseyAutoConfigurationDefaultServletPathTests { @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration - @Import({ ServletWebServerFactoryAutoConfiguration.class, JerseyAutoConfiguration.class, + @Import({ TomcatServletWebServerAutoConfiguration.class, JerseyAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class }) protected @interface MinimalWebConfiguration { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationObjectMapperProviderTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationObjectMapperProviderTests.java index 59cc5167b3..f276627071 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationObjectMapperProviderTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationObjectMapperProviderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,7 +33,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; @@ -127,7 +127,7 @@ class JerseyAutoConfigurationObjectMapperProviderTests { @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration - @Import({ ServletWebServerFactoryAutoConfiguration.class, JacksonAutoConfiguration.class, + @Import({ TomcatServletWebServerAutoConfiguration.class, JacksonAutoConfiguration.class, JerseyAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class }) protected @interface MinimalWebConfiguration { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationServletContainerTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationServletContainerTests.java index c840532382..c5ec988b32 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationServletContainerTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationServletContainerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,12 +32,12 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.jersey.JerseyAutoConfigurationServletContainerTests.Application; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.system.CapturedOutput; import org.springframework.boot.test.system.OutputCaptureExtension; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @@ -62,7 +62,7 @@ class JerseyAutoConfigurationServletContainerTests { assertThat(output).contains("Servlet " + Application.class.getName() + " was not registered"); } - @ImportAutoConfiguration({ ServletWebServerFactoryAutoConfiguration.class, JerseyAutoConfiguration.class, + @ImportAutoConfiguration({ TomcatServletWebServerAutoConfiguration.class, JerseyAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class }) @Import(ContainerConfiguration.class) @Path("/hello") diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationWithoutApplicationPathTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationWithoutApplicationPathTests.java index f67bee8c77..c919f59c3a 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationWithoutApplicationPathTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfigurationWithoutApplicationPathTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,7 +31,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; @@ -87,7 +87,7 @@ class JerseyAutoConfigurationWithoutApplicationPathTests { @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration - @Import({ ServletWebServerFactoryAutoConfiguration.class, JerseyAutoConfiguration.class, + @Import({ TomcatServletWebServerAutoConfiguration.class, JerseyAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class }) protected @interface MinimalWebConfiguration { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheAutoConfigurationReactiveIntegrationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheAutoConfigurationReactiveIntegrationTests.java index 0836b7d717..1471fc3cc4 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheAutoConfigurationReactiveIntegrationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheAutoConfigurationReactiveIntegrationTests.java @@ -26,8 +26,8 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration; -import org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration; import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.reactive.netty.NettyReactiveWebServerAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.web.reactive.result.view.MustacheView; @@ -81,7 +81,7 @@ class MustacheAutoConfigurationReactiveIntegrationTests { } @Configuration(proxyBeanMethods = false) - @Import({ ReactiveWebServerFactoryAutoConfiguration.class, WebFluxAutoConfiguration.class, + @Import({ NettyReactiveWebServerAutoConfiguration.class, WebFluxAutoConfiguration.class, HttpHandlerAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class }) @Controller static class Application { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheAutoConfigurationServletIntegrationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheAutoConfigurationServletIntegrationTests.java index aba169ffc3..ea93a298f6 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheAutoConfigurationServletIntegrationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheAutoConfigurationServletIntegrationTests.java @@ -33,8 +33,8 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; @@ -132,7 +132,7 @@ class MustacheAutoConfigurationServletIntegrationTests { @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented - @Import({ ServletWebServerFactoryAutoConfiguration.class, DispatcherServletAutoConfiguration.class, + @Import({ TomcatServletWebServerAutoConfiguration.class, DispatcherServletAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class }) protected @interface MinimalWebConfiguration { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/rsocket/RSocketWebSocketNettyRouteProviderTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/rsocket/RSocketWebSocketNettyRouteProviderTests.java index 542e22b168..4da6a77aee 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/rsocket/RSocketWebSocketNettyRouteProviderTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/rsocket/RSocketWebSocketNettyRouteProviderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,10 +29,10 @@ import org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfig import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration; import org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration; import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; -import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext; import org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext; import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.reactive.netty.NettyReactiveWebServerFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/client/servlet/OAuth2ClientWebSecurityAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/client/servlet/OAuth2ClientWebSecurityAutoConfigurationTests.java index 95a57db122..f7008e5391 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/client/servlet/OAuth2ClientWebSecurityAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/client/servlet/OAuth2ClientWebSecurityAutoConfigurationTests.java @@ -27,7 +27,7 @@ import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguratio import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/servlet/SecurityFilterAutoConfigurationEarlyInitializationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/servlet/SecurityFilterAutoConfigurationEarlyInitializationTests.java index 40bcf8bddc..c2d8006043 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/servlet/SecurityFilterAutoConfigurationEarlyInitializationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/servlet/SecurityFilterAutoConfigurationEarlyInitializationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,7 +39,7 @@ import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.boot.testsupport.classpath.ClassPathExclusions; import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/AbstractSessionAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/AbstractSessionAutoConfigurationTests.java index f6203e7076..c9739839ce 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/AbstractSessionAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/AbstractSessionAutoConfigurationTests.java @@ -23,7 +23,7 @@ import org.springframework.boot.test.context.assertj.AssertableReactiveWebApplic import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext; import org.springframework.boot.test.context.runner.ContextConsumer; import org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext; -import org.springframework.boot.web.reactive.server.MockReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.MockReactiveWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.mock.http.server.reactive.MockServerHttpRequest; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationEarlyInitializationIntegrationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationEarlyInitializationIntegrationTests.java index 5b16c33516..47c229c4c8 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationEarlyInitializationIntegrationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationEarlyInitializationIntegrationTests.java @@ -21,7 +21,7 @@ import java.util.LinkedHashMap; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.context.ConfigurableApplicationContext; @@ -52,7 +52,7 @@ class SessionAutoConfigurationEarlyInitializationIntegrationTests { @Configuration(proxyBeanMethods = false) @EnableSpringHttpSession - @ImportAutoConfiguration({ ServletWebServerFactoryAutoConfiguration.class, SessionAutoConfiguration.class }) + @ImportAutoConfiguration({ TomcatServletWebServerAutoConfiguration.class, SessionAutoConfiguration.class }) static class TestConfiguration { @Bean diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java index 55c4183280..98eff18d77 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java @@ -44,11 +44,11 @@ import org.springframework.boot.context.properties.bind.Binder; import org.springframework.boot.context.properties.source.ConfigurationPropertySource; import org.springframework.boot.context.properties.source.MapConfigurationPropertySource; import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories; -import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory; -import org.springframework.boot.web.embedded.jetty.JettyWebServer; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.MimeMappings; import org.springframework.boot.web.server.MimeMappings.Mapping; +import org.springframework.boot.web.server.jetty.JettyWebServer; +import org.springframework.boot.web.server.servlet.jetty.JettyServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.util.unit.DataSize; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/UndertowWebServerFactoryCustomizerConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/UndertowWebServerFactoryCustomizerConfigurationTests.java deleted file mode 100644 index 927462ecfb..0000000000 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/UndertowWebServerFactoryCustomizerConfigurationTests.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2012-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.autoconfigure.web.embedded; - -import io.undertow.servlet.api.DeploymentInfo; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.EnabledForJreRange; -import org.junit.jupiter.api.condition.JRE; - -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration.UndertowWebServerFactoryCustomizerConfiguration; -import org.springframework.boot.test.context.runner.WebApplicationContextRunner; -import org.springframework.boot.web.embedded.undertow.UndertowDeploymentInfoCustomizer; -import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebApplicationContext; -import org.springframework.core.task.VirtualThreadTaskExecutor; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link UndertowWebServerFactoryCustomizerConfiguration}. - * - * @author Moritz Halbritter - */ -class UndertowWebServerFactoryCustomizerConfigurationTests { - - private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner( - AnnotationConfigServletWebApplicationContext::new) - .withConfiguration(AutoConfigurations.of(EmbeddedWebServerFactoryCustomizerAutoConfiguration.class)); - - @EnabledForJreRange(min = JRE.JAVA_21) - @Test - void shouldUseVirtualThreadsIfEnabled() { - this.contextRunner.withPropertyValues("spring.threads.virtual.enabled=true").run((context) -> { - assertThat(context).hasSingleBean(UndertowDeploymentInfoCustomizer.class); - assertThat(context).hasBean("virtualThreadsUndertowDeploymentInfoCustomizer"); - UndertowDeploymentInfoCustomizer customizer = context.getBean(UndertowDeploymentInfoCustomizer.class); - DeploymentInfo deploymentInfo = new DeploymentInfo(); - customizer.customize(deploymentInfo); - assertThat(deploymentInfo.getExecutor()).isInstanceOf(VirtualThreadTaskExecutor.class); - }); - } - -} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/ReactiveWebServerFactoryAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/ReactiveWebServerFactoryAutoConfigurationTests.java deleted file mode 100644 index d10f6185a6..0000000000 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/ReactiveWebServerFactoryAutoConfigurationTests.java +++ /dev/null @@ -1,569 +0,0 @@ -/* - * Copyright 2012-2025 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.autoconfigure.web.reactive; - -import io.undertow.Undertow; -import io.undertow.Undertow.Builder; -import org.apache.catalina.Context; -import org.apache.catalina.connector.Connector; -import org.apache.catalina.startup.Tomcat; -import org.eclipse.jetty.server.Server; -import org.junit.jupiter.api.Test; -import reactor.netty.http.server.HttpServer; - -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration; -import org.springframework.boot.ssl.NoSuchSslBundleException; -import org.springframework.boot.test.context.FilteredClassLoader; -import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; -import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories; -import org.springframework.boot.web.embedded.jetty.JettyReactiveWebServerFactory; -import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer; -import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; -import org.springframework.boot.web.embedded.netty.NettyServerCustomizer; -import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer; -import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer; -import org.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer; -import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory; -import org.springframework.boot.web.embedded.undertow.UndertowBuilderCustomizer; -import org.springframework.boot.web.embedded.undertow.UndertowDeploymentInfoCustomizer; -import org.springframework.boot.web.embedded.undertow.UndertowReactiveWebServerFactory; -import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebApplicationContext; -import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext; -import org.springframework.boot.web.reactive.server.ConfigurableReactiveWebServerFactory; -import org.springframework.boot.web.reactive.server.MockReactiveWebServerFactory; -import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; -import org.springframework.boot.web.server.WebServerFactoryCustomizer; -import org.springframework.context.ApplicationContextException; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.server.reactive.HttpHandler; -import org.springframework.web.server.adapter.ForwardedHeaderTransformer; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.mock; - -/** - * Tests for {@link ReactiveWebServerFactoryAutoConfiguration}. - * - * @author Brian Clozel - * @author Raheela Aslam - * @author Madhura Bhave - * @author Scott Frederick - */ -@DirtiesUrlFactories -class ReactiveWebServerFactoryAutoConfigurationTests { - - private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner( - AnnotationConfigReactiveWebServerApplicationContext::new) - .withConfiguration( - AutoConfigurations.of(ReactiveWebServerFactoryAutoConfiguration.class, SslAutoConfiguration.class)); - - @Test - void createFromConfigClass() { - this.contextRunner.withUserConfiguration(MockWebServerConfiguration.class, HttpHandlerConfiguration.class) - .run((context) -> { - assertThat(context.getBeansOfType(ReactiveWebServerFactory.class)).hasSize(1); - assertThat(context.getBeansOfType(WebServerFactoryCustomizer.class)).hasSize(2); - assertThat(context.getBeansOfType(ReactiveWebServerFactoryCustomizer.class)).hasSize(1); - }); - } - - @Test - void missingHttpHandler() { - this.contextRunner.withUserConfiguration(MockWebServerConfiguration.class) - .run((context) -> assertThat(context.getStartupFailure()).isInstanceOf(ApplicationContextException.class) - .rootCause() - .hasMessageContaining("missing HttpHandler bean")); - } - - @Test - void multipleHttpHandler() { - this.contextRunner - .withUserConfiguration(MockWebServerConfiguration.class, HttpHandlerConfiguration.class, - TooManyHttpHandlers.class) - .run((context) -> assertThat(context.getStartupFailure()).isInstanceOf(ApplicationContextException.class) - .rootCause() - .hasMessageContaining("multiple HttpHandler beans : httpHandler,additionalHttpHandler")); - } - - @Test - void customizeReactiveWebServer() { - this.contextRunner - .withUserConfiguration(MockWebServerConfiguration.class, HttpHandlerConfiguration.class, - ReactiveWebServerCustomization.class) - .run((context) -> assertThat(context.getBean(MockReactiveWebServerFactory.class).getPort()) - .isEqualTo(9000)); - } - - @Test - void defaultWebServerIsTomcat() { - // Tomcat should be chosen over Netty if the Tomcat library is present. - this.contextRunner.withUserConfiguration(HttpHandlerConfiguration.class) - .withPropertyValues("server.port=0") - .run((context) -> assertThat(context.getBean(ReactiveWebServerFactory.class)) - .isInstanceOf(TomcatReactiveWebServerFactory.class)); - } - - @Test - void webServerFailsWithInvalidSslBundle() { - this.contextRunner.withUserConfiguration(HttpHandlerConfiguration.class) - .withPropertyValues("server.port=0", "server.ssl.bundle=test-bundle") - .run((context) -> { - assertThat(context).hasFailed(); - assertThat(context.getStartupFailure().getCause()).isInstanceOf(NoSuchSslBundleException.class) - .withFailMessage("test"); - }); - } - - @Test - void tomcatConnectorCustomizerBeanIsAddedToFactory() { - ReactiveWebApplicationContextRunner runner = new ReactiveWebApplicationContextRunner( - AnnotationConfigReactiveWebServerApplicationContext::new) - .withConfiguration(AutoConfigurations.of(ReactiveWebServerFactoryAutoConfiguration.class)) - .withUserConfiguration(HttpHandlerConfiguration.class, TomcatConnectorCustomizerConfiguration.class) - .withPropertyValues("server.port: 0"); - runner.run((context) -> { - TomcatReactiveWebServerFactory factory = context.getBean(TomcatReactiveWebServerFactory.class); - TomcatConnectorCustomizer customizer = context.getBean("connectorCustomizer", - TomcatConnectorCustomizer.class); - assertThat(factory.getTomcatConnectorCustomizers()).contains(customizer); - then(customizer).should().customize(any(Connector.class)); - }); - } - - @Test - void tomcatConnectorCustomizerRegisteredAsBeanAndViaFactoryIsOnlyCalledOnce() { - ReactiveWebApplicationContextRunner runner = new ReactiveWebApplicationContextRunner( - AnnotationConfigReactiveWebServerApplicationContext::new) - .withConfiguration(AutoConfigurations.of(ReactiveWebServerFactoryAutoConfiguration.class)) - .withUserConfiguration(HttpHandlerConfiguration.class, - DoubleRegistrationTomcatConnectorCustomizerConfiguration.class) - .withPropertyValues("server.port: 0"); - runner.run((context) -> { - TomcatReactiveWebServerFactory factory = context.getBean(TomcatReactiveWebServerFactory.class); - TomcatConnectorCustomizer customizer = context.getBean("connectorCustomizer", - TomcatConnectorCustomizer.class); - assertThat(factory.getTomcatConnectorCustomizers()).contains(customizer); - then(customizer).should().customize(any(Connector.class)); - }); - } - - @Test - void tomcatContextCustomizerBeanIsAddedToFactory() { - ReactiveWebApplicationContextRunner runner = new ReactiveWebApplicationContextRunner( - AnnotationConfigReactiveWebServerApplicationContext::new) - .withConfiguration(AutoConfigurations.of(ReactiveWebServerFactoryAutoConfiguration.class)) - .withUserConfiguration(HttpHandlerConfiguration.class, TomcatContextCustomizerConfiguration.class) - .withPropertyValues("server.port: 0"); - runner.run((context) -> { - TomcatReactiveWebServerFactory factory = context.getBean(TomcatReactiveWebServerFactory.class); - TomcatContextCustomizer customizer = context.getBean("contextCustomizer", TomcatContextCustomizer.class); - assertThat(factory.getTomcatContextCustomizers()).contains(customizer); - then(customizer).should().customize(any(Context.class)); - }); - } - - @Test - void tomcatContextCustomizerRegisteredAsBeanAndViaFactoryIsOnlyCalledOnce() { - ReactiveWebApplicationContextRunner runner = new ReactiveWebApplicationContextRunner( - AnnotationConfigReactiveWebServerApplicationContext::new) - .withConfiguration(AutoConfigurations.of(ReactiveWebServerFactoryAutoConfiguration.class)) - .withUserConfiguration(HttpHandlerConfiguration.class, - DoubleRegistrationTomcatContextCustomizerConfiguration.class) - .withPropertyValues("server.port: 0"); - runner.run((context) -> { - TomcatReactiveWebServerFactory factory = context.getBean(TomcatReactiveWebServerFactory.class); - TomcatContextCustomizer customizer = context.getBean("contextCustomizer", TomcatContextCustomizer.class); - assertThat(factory.getTomcatContextCustomizers()).contains(customizer); - then(customizer).should().customize(any(Context.class)); - }); - } - - @Test - void tomcatProtocolHandlerCustomizerBeanIsAddedToFactory() { - ReactiveWebApplicationContextRunner runner = new ReactiveWebApplicationContextRunner( - AnnotationConfigReactiveWebServerApplicationContext::new) - .withConfiguration(AutoConfigurations.of(ReactiveWebServerFactoryAutoConfiguration.class)) - .withUserConfiguration(HttpHandlerConfiguration.class, TomcatProtocolHandlerCustomizerConfiguration.class) - .withPropertyValues("server.port: 0"); - runner.run((context) -> { - TomcatReactiveWebServerFactory factory = context.getBean(TomcatReactiveWebServerFactory.class); - TomcatProtocolHandlerCustomizer customizer = context.getBean("protocolHandlerCustomizer", - TomcatProtocolHandlerCustomizer.class); - assertThat(factory.getTomcatProtocolHandlerCustomizers()).contains(customizer); - then(customizer).should().customize(any()); - }); - } - - @Test - void tomcatProtocolHandlerCustomizerRegisteredAsBeanAndViaFactoryIsOnlyCalledOnce() { - ReactiveWebApplicationContextRunner runner = new ReactiveWebApplicationContextRunner( - AnnotationConfigReactiveWebServerApplicationContext::new) - .withConfiguration(AutoConfigurations.of(ReactiveWebServerFactoryAutoConfiguration.class)) - .withUserConfiguration(HttpHandlerConfiguration.class, - DoubleRegistrationTomcatProtocolHandlerCustomizerConfiguration.class) - .withPropertyValues("server.port: 0"); - runner.run((context) -> { - TomcatReactiveWebServerFactory factory = context.getBean(TomcatReactiveWebServerFactory.class); - TomcatProtocolHandlerCustomizer customizer = context.getBean("protocolHandlerCustomizer", - TomcatProtocolHandlerCustomizer.class); - assertThat(factory.getTomcatProtocolHandlerCustomizers()).contains(customizer); - then(customizer).should().customize(any()); - }); - } - - @Test - void jettyServerCustomizerBeanIsAddedToFactory() { - new ReactiveWebApplicationContextRunner(AnnotationConfigReactiveWebApplicationContext::new) - .withConfiguration(AutoConfigurations.of(ReactiveWebServerFactoryAutoConfiguration.class)) - .withClassLoader(new FilteredClassLoader(Tomcat.class, HttpServer.class)) - .withUserConfiguration(JettyServerCustomizerConfiguration.class, HttpHandlerConfiguration.class) - .run((context) -> { - JettyReactiveWebServerFactory factory = context.getBean(JettyReactiveWebServerFactory.class); - assertThat(factory.getServerCustomizers()).hasSize(1); - }); - } - - @Test - void jettyServerCustomizerRegisteredAsBeanAndViaFactoryIsOnlyCalledOnce() { - new ReactiveWebApplicationContextRunner(AnnotationConfigReactiveWebServerApplicationContext::new) - .withConfiguration(AutoConfigurations.of(ReactiveWebServerFactoryAutoConfiguration.class)) - .withClassLoader(new FilteredClassLoader(Tomcat.class, HttpServer.class)) - .withUserConfiguration(DoubleRegistrationJettyServerCustomizerConfiguration.class, - HttpHandlerConfiguration.class) - .withPropertyValues("server.port=0") - .run((context) -> { - JettyReactiveWebServerFactory factory = context.getBean(JettyReactiveWebServerFactory.class); - JettyServerCustomizer customizer = context.getBean("serverCustomizer", JettyServerCustomizer.class); - assertThat(factory.getServerCustomizers()).contains(customizer); - then(customizer).should().customize(any(Server.class)); - }); - } - - @Test - void undertowBuilderCustomizerBeanIsAddedToFactory() { - new ReactiveWebApplicationContextRunner(AnnotationConfigReactiveWebApplicationContext::new) - .withConfiguration(AutoConfigurations.of(ReactiveWebServerFactoryAutoConfiguration.class)) - .withClassLoader(new FilteredClassLoader(Tomcat.class, HttpServer.class, Server.class)) - .withUserConfiguration(UndertowBuilderCustomizerConfiguration.class, HttpHandlerConfiguration.class) - .run((context) -> { - UndertowReactiveWebServerFactory factory = context.getBean(UndertowReactiveWebServerFactory.class); - assertThat(factory.getBuilderCustomizers()).hasSize(1); - }); - } - - @Test - void undertowBuilderCustomizerRegisteredAsBeanAndViaFactoryIsOnlyCalledOnce() { - new ReactiveWebApplicationContextRunner(AnnotationConfigReactiveWebServerApplicationContext::new) - .withConfiguration(AutoConfigurations.of(ReactiveWebServerFactoryAutoConfiguration.class)) - .withClassLoader(new FilteredClassLoader(Tomcat.class, HttpServer.class, Server.class)) - .withUserConfiguration(DoubleRegistrationUndertowBuilderCustomizerConfiguration.class, - HttpHandlerConfiguration.class) - .withPropertyValues("server.port: 0") - .run((context) -> { - UndertowReactiveWebServerFactory factory = context.getBean(UndertowReactiveWebServerFactory.class); - UndertowBuilderCustomizer customizer = context.getBean("builderCustomizer", - UndertowBuilderCustomizer.class); - assertThat(factory.getBuilderCustomizers()).contains(customizer); - then(customizer).should().customize(any(Builder.class)); - }); - } - - @Test - void nettyServerCustomizerBeanIsAddedToFactory() { - new ReactiveWebApplicationContextRunner(AnnotationConfigReactiveWebApplicationContext::new) - .withConfiguration(AutoConfigurations.of(ReactiveWebServerFactoryAutoConfiguration.class)) - .withClassLoader(new FilteredClassLoader(Tomcat.class, Server.class, Undertow.class)) - .withUserConfiguration(NettyServerCustomizerConfiguration.class, HttpHandlerConfiguration.class) - .run((context) -> { - NettyReactiveWebServerFactory factory = context.getBean(NettyReactiveWebServerFactory.class); - assertThat(factory.getServerCustomizers()).hasSize(1); - }); - } - - @Test - void nettyServerCustomizerRegisteredAsBeanAndViaFactoryIsOnlyCalledOnce() { - new ReactiveWebApplicationContextRunner(AnnotationConfigReactiveWebServerApplicationContext::new) - .withConfiguration(AutoConfigurations.of(ReactiveWebServerFactoryAutoConfiguration.class)) - .withClassLoader(new FilteredClassLoader(Tomcat.class, Server.class, Undertow.class)) - .withUserConfiguration(DoubleRegistrationNettyServerCustomizerConfiguration.class, - HttpHandlerConfiguration.class) - .withPropertyValues("server.port: 0") - .run((context) -> { - NettyReactiveWebServerFactory factory = context.getBean(NettyReactiveWebServerFactory.class); - NettyServerCustomizer customizer = context.getBean("serverCustomizer", NettyServerCustomizer.class); - assertThat(factory.getServerCustomizers()).contains(customizer); - then(customizer).should().apply(any(HttpServer.class)); - }); - } - - @Test - void forwardedHeaderTransformerShouldBeConfigured() { - this.contextRunner.withUserConfiguration(HttpHandlerConfiguration.class) - .withPropertyValues("server.forward-headers-strategy=framework", "server.port=0") - .run((context) -> assertThat(context).hasSingleBean(ForwardedHeaderTransformer.class)); - } - - @Test - void forwardedHeaderTransformerWhenStrategyNotFilterShouldNotBeConfigured() { - this.contextRunner.withUserConfiguration(HttpHandlerConfiguration.class) - .withPropertyValues("server.forward-headers-strategy=native", "server.port=0") - .run((context) -> assertThat(context).doesNotHaveBean(ForwardedHeaderTransformer.class)); - } - - @Test - void forwardedHeaderTransformerWhenAlreadyRegisteredShouldBackOff() { - this.contextRunner - .withUserConfiguration(ForwardedHeaderTransformerConfiguration.class, HttpHandlerConfiguration.class) - .withPropertyValues("server.forward-headers-strategy=framework", "server.port=0") - .run((context) -> assertThat(context).hasSingleBean(ForwardedHeaderTransformer.class)); - } - - @Configuration(proxyBeanMethods = false) - static class HttpHandlerConfiguration { - - @Bean - HttpHandler httpHandler() { - return mock(HttpHandler.class); - } - - } - - @Configuration(proxyBeanMethods = false) - static class TooManyHttpHandlers { - - @Bean - HttpHandler additionalHttpHandler() { - return mock(HttpHandler.class); - } - - } - - @Configuration(proxyBeanMethods = false) - static class ReactiveWebServerCustomization { - - @Bean - WebServerFactoryCustomizer reactiveWebServerCustomizer() { - return (factory) -> factory.setPort(9000); - } - - } - - @Configuration(proxyBeanMethods = false) - static class MockWebServerConfiguration { - - @Bean - MockReactiveWebServerFactory mockReactiveWebServerFactory() { - return new MockReactiveWebServerFactory(); - } - - } - - @Configuration(proxyBeanMethods = false) - static class TomcatConnectorCustomizerConfiguration { - - @Bean - TomcatConnectorCustomizer connectorCustomizer() { - return mock(TomcatConnectorCustomizer.class); - } - - } - - @Configuration(proxyBeanMethods = false) - static class DoubleRegistrationTomcatConnectorCustomizerConfiguration { - - private final TomcatConnectorCustomizer customizer = mock(TomcatConnectorCustomizer.class); - - @Bean - TomcatConnectorCustomizer connectorCustomizer() { - return this.customizer; - } - - @Bean - WebServerFactoryCustomizer tomcatCustomizer() { - return (tomcat) -> tomcat.addConnectorCustomizers(this.customizer); - } - - } - - @Configuration(proxyBeanMethods = false) - static class TomcatContextCustomizerConfiguration { - - @Bean - TomcatContextCustomizer contextCustomizer() { - return mock(TomcatContextCustomizer.class); - } - - } - - @Configuration(proxyBeanMethods = false) - static class DoubleRegistrationTomcatContextCustomizerConfiguration { - - private final TomcatContextCustomizer customizer = mock(TomcatContextCustomizer.class); - - @Bean - TomcatContextCustomizer contextCustomizer() { - return this.customizer; - } - - @Bean - WebServerFactoryCustomizer tomcatCustomizer() { - return (tomcat) -> tomcat.addContextCustomizers(this.customizer); - } - - } - - @Configuration(proxyBeanMethods = false) - static class TomcatProtocolHandlerCustomizerConfiguration { - - @Bean - TomcatProtocolHandlerCustomizer protocolHandlerCustomizer() { - return mock(TomcatProtocolHandlerCustomizer.class); - } - - } - - @Configuration(proxyBeanMethods = false) - static class DoubleRegistrationTomcatProtocolHandlerCustomizerConfiguration { - - private final TomcatProtocolHandlerCustomizer customizer = mock(TomcatProtocolHandlerCustomizer.class); - - @Bean - TomcatProtocolHandlerCustomizer protocolHandlerCustomizer() { - return this.customizer; - } - - @Bean - WebServerFactoryCustomizer tomcatCustomizer() { - return (tomcat) -> tomcat.addProtocolHandlerCustomizers(this.customizer); - } - - } - - @Configuration(proxyBeanMethods = false) - static class JettyServerCustomizerConfiguration { - - @Bean - JettyServerCustomizer serverCustomizer() { - return (server) -> { - }; - } - - } - - @Configuration(proxyBeanMethods = false) - static class DoubleRegistrationJettyServerCustomizerConfiguration { - - private final JettyServerCustomizer customizer = mock(JettyServerCustomizer.class); - - @Bean - JettyServerCustomizer serverCustomizer() { - return this.customizer; - } - - @Bean - WebServerFactoryCustomizer jettyCustomizer() { - return (jetty) -> jetty.addServerCustomizers(this.customizer); - } - - } - - @Configuration(proxyBeanMethods = false) - static class UndertowBuilderCustomizerConfiguration { - - @Bean - UndertowBuilderCustomizer builderCustomizer() { - return (builder) -> { - }; - } - - } - - @Configuration(proxyBeanMethods = false) - static class DoubleRegistrationUndertowBuilderCustomizerConfiguration { - - private final UndertowBuilderCustomizer customizer = mock(UndertowBuilderCustomizer.class); - - @Bean - UndertowBuilderCustomizer builderCustomizer() { - return this.customizer; - } - - @Bean - WebServerFactoryCustomizer undertowCustomizer() { - return (undertow) -> undertow.addBuilderCustomizers(this.customizer); - } - - } - - @Configuration(proxyBeanMethods = false) - static class UndertowDeploymentInfoCustomizerConfiguration { - - @Bean - UndertowDeploymentInfoCustomizer deploymentInfoCustomizer() { - return (deploymentInfo) -> { - }; - } - - } - - @Configuration(proxyBeanMethods = false) - static class NettyServerCustomizerConfiguration { - - @Bean - NettyServerCustomizer serverCustomizer() { - return (server) -> server; - } - - } - - @Configuration(proxyBeanMethods = false) - static class DoubleRegistrationNettyServerCustomizerConfiguration { - - private final NettyServerCustomizer customizer = mock(NettyServerCustomizer.class); - - DoubleRegistrationNettyServerCustomizerConfiguration() { - given(this.customizer.apply(any(HttpServer.class))).willAnswer((invocation) -> invocation.getArgument(0)); - } - - @Bean - NettyServerCustomizer serverCustomizer() { - return this.customizer; - } - - @Bean - WebServerFactoryCustomizer nettyCustomizer() { - return (netty) -> netty.addServerCustomizers(this.customizer); - } - - } - - @Configuration(proxyBeanMethods = false) - static class ForwardedHeaderTransformerConfiguration { - - @Bean - ForwardedHeaderTransformer testForwardedHeaderTransformer() { - return new ForwardedHeaderTransformer(); - } - - } - -} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java index c7bd34d8be..c147fd1a38 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java @@ -61,7 +61,7 @@ import org.springframework.boot.testsupport.classpath.resources.WithResource; import org.springframework.boot.web.codec.CodecCustomizer; import org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext; import org.springframework.boot.web.reactive.filter.OrderedHiddenHttpMethodFilter; -import org.springframework.boot.web.reactive.server.MockReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.MockReactiveWebServerFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandlerIntegrationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandlerIntegrationTests.java index 01c1481f91..2863cc16c5 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandlerIntegrationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandlerIntegrationTests.java @@ -36,8 +36,8 @@ import org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.autoconfigure.web.WebProperties; import org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration; -import org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration; import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.reactive.netty.NettyReactiveWebServerAutoConfiguration; import org.springframework.boot.test.context.assertj.AssertableReactiveWebApplicationContext; import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; import org.springframework.boot.test.system.CapturedOutput; @@ -86,7 +86,7 @@ class DefaultErrorWebExceptionHandlerIntegrationTests { private final LogIdFilter logIdFilter = new LogIdFilter(); private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(ReactiveWebServerFactoryAutoConfiguration.class, + .withConfiguration(AutoConfigurations.of(NettyReactiveWebServerAutoConfiguration.class, HttpHandlerAutoConfiguration.class, WebFluxAutoConfiguration.class, ErrorWebFluxAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class, MustacheAutoConfiguration.class)) .withPropertyValues("spring.main.web-application-type=reactive", "server.port=0") diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/JettyVirtualThreadsWebServerFactoryCustomizerTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/jetty/JettyVirtualThreadsWebServerFactoryCustomizerTests.java similarity index 92% rename from spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/JettyVirtualThreadsWebServerFactoryCustomizerTests.java rename to spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/jetty/JettyVirtualThreadsWebServerFactoryCustomizerTests.java index b98016ea9b..21ab20503e 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/JettyVirtualThreadsWebServerFactoryCustomizerTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/jetty/JettyVirtualThreadsWebServerFactoryCustomizerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.web.embedded; +package org.springframework.boot.autoconfigure.web.server.jetty; import java.time.Duration; import java.util.concurrent.Executor; @@ -28,7 +28,7 @@ import org.junit.jupiter.api.condition.EnabledForJreRange; import org.junit.jupiter.api.condition.JRE; import org.springframework.boot.autoconfigure.web.ServerProperties; -import org.springframework.boot.web.embedded.jetty.ConfigurableJettyWebServerFactory; +import org.springframework.boot.web.server.jetty.ConfigurableJettyWebServerFactory; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.assertArg; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/JettyWebServerFactoryCustomizerTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/jetty/JettyWebServerFactoryCustomizerTests.java similarity index 97% rename from spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/JettyWebServerFactoryCustomizerTests.java rename to spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/jetty/JettyWebServerFactoryCustomizerTests.java index cf2970c1ec..5ed056e970 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/JettyWebServerFactoryCustomizerTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/jetty/JettyWebServerFactoryCustomizerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.web.embedded; +package org.springframework.boot.autoconfigure.web.server.jetty; import java.io.File; import java.io.IOException; @@ -48,9 +48,9 @@ import org.springframework.boot.context.properties.bind.Bindable; import org.springframework.boot.context.properties.bind.Binder; import org.springframework.boot.context.properties.source.ConfigurationPropertySources; import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories; -import org.springframework.boot.web.embedded.jetty.ConfigurableJettyWebServerFactory; -import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory; -import org.springframework.boot.web.embedded.jetty.JettyWebServer; +import org.springframework.boot.web.server.jetty.ConfigurableJettyWebServerFactory; +import org.springframework.boot.web.server.jetty.JettyWebServer; +import org.springframework.boot.web.server.servlet.jetty.JettyServletWebServerFactory; import org.springframework.mock.env.MockEnvironment; import org.springframework.test.context.support.TestPropertySourceUtils; import org.springframework.test.util.ReflectionTestUtils; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/reactive/AbstractReactiveWebServerAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/reactive/AbstractReactiveWebServerAutoConfigurationTests.java new file mode 100644 index 0000000000..e676c40a5f --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/reactive/AbstractReactiveWebServerAutoConfigurationTests.java @@ -0,0 +1,187 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.web.server.reactive; + +import org.junit.jupiter.api.Test; + +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.ssl.DefaultSslBundleRegistry; +import org.springframework.boot.ssl.NoSuchSslBundleException; +import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; +import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext; +import org.springframework.boot.web.server.ConfigurableWebServerFactory; +import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.reactive.ConfigurableReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.MockReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.ReactiveWebServerFactory; +import org.springframework.context.ApplicationContextException; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.server.reactive.HttpHandler; +import org.springframework.web.server.adapter.ForwardedHeaderTransformer; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + +/** + * Base class for testing sub-classes of {@link ReactiveWebServerConfiguration}. + * + * @author Brian Clozel + * @author Raheela Aslam + * @author Madhura Bhave + * @author Scott Frederick + */ +// @DirtiesUrlFactories +public abstract class AbstractReactiveWebServerAutoConfigurationTests { + + private final ReactiveWebApplicationContextRunner mockServerRunner; + + protected final ReactiveWebApplicationContextRunner serverRunner; + + protected AbstractReactiveWebServerAutoConfigurationTests(Class serverAutoConfiguration) { + ReactiveWebApplicationContextRunner common = new ReactiveWebApplicationContextRunner( + AnnotationConfigReactiveWebServerApplicationContext::new) + .withConfiguration(AutoConfigurations.of(serverAutoConfiguration)); + this.serverRunner = common.withPropertyValues("server.port=0") + .withUserConfiguration(HttpHandlerConfiguration.class); + this.mockServerRunner = common.withUserConfiguration(MockWebServerConfiguration.class); + } + + @Test + void createFromConfigClass() { + this.mockServerRunner.withUserConfiguration(MockWebServerConfiguration.class, HttpHandlerConfiguration.class) + .run((context) -> { + assertThat(context.getBeansOfType(ReactiveWebServerFactory.class)).hasSize(1); + assertThat(context.getBeansOfType(WebServerFactoryCustomizer.class)).hasSizeGreaterThanOrEqualTo(1); + assertThat(context.getBeansOfType(ReactiveWebServerFactoryCustomizer.class)).hasSize(1); + }); + } + + @Test + void missingHttpHandler() { + this.mockServerRunner.withUserConfiguration(MockWebServerConfiguration.class) + .run((context) -> assertThat(context.getStartupFailure()).isInstanceOf(ApplicationContextException.class) + .rootCause() + .hasMessageContaining("missing HttpHandler bean")); + } + + @Test + void multipleHttpHandler() { + this.mockServerRunner + .withUserConfiguration(MockWebServerConfiguration.class, HttpHandlerConfiguration.class, + TooManyHttpHandlers.class) + .run((context) -> assertThat(context.getStartupFailure()).isInstanceOf(ApplicationContextException.class) + .rootCause() + .hasMessageContaining("multiple HttpHandler beans : httpHandler,additionalHttpHandler")); + } + + @Test + void customizeReactiveWebServer() { + this.mockServerRunner + .withUserConfiguration(MockWebServerConfiguration.class, HttpHandlerConfiguration.class, + ReactiveWebServerCustomization.class) + .run((context) -> assertThat(context.getBean(MockReactiveWebServerFactory.class).getPort()) + .isEqualTo(9000)); + } + + @Test + void webServerFailsWithInvalidSslBundle() { + this.serverRunner.withUserConfiguration(HttpHandlerConfiguration.class) + .withBean(WebServerFactoryCustomizer.class, + () -> (WebServerFactoryCustomizer) (factory) -> factory + .setSslBundles(new DefaultSslBundleRegistry())) + .withPropertyValues("server.ssl.bundle=test-bundle") + .run((context) -> { + assertThat(context).hasFailed(); + assertThat(context.getStartupFailure().getCause()).isInstanceOf(NoSuchSslBundleException.class) + .withFailMessage("test"); + }); + } + + @Test + void forwardedHeaderTransformerShouldBeConfigured() { + this.mockServerRunner.withUserConfiguration(HttpHandlerConfiguration.class) + .withPropertyValues("server.forward-headers-strategy=framework", "server.port=0") + .run((context) -> assertThat(context).hasSingleBean(ForwardedHeaderTransformer.class)); + } + + @Test + void forwardedHeaderTransformerWhenStrategyNotFilterShouldNotBeConfigured() { + this.mockServerRunner.withUserConfiguration(HttpHandlerConfiguration.class) + .withPropertyValues("server.forward-headers-strategy=native", "server.port=0") + .run((context) -> assertThat(context).doesNotHaveBean(ForwardedHeaderTransformer.class)); + } + + @Test + void forwardedHeaderTransformerWhenAlreadyRegisteredShouldBackOff() { + this.mockServerRunner + .withUserConfiguration(ForwardedHeaderTransformerConfiguration.class, HttpHandlerConfiguration.class) + .withPropertyValues("server.forward-headers-strategy=framework", "server.port=0") + .run((context) -> assertThat(context).hasSingleBean(ForwardedHeaderTransformer.class)); + } + + @Configuration(proxyBeanMethods = false) + static class HttpHandlerConfiguration { + + @Bean + HttpHandler httpHandler() { + return mock(HttpHandler.class); + } + + } + + @Configuration(proxyBeanMethods = false) + static class TooManyHttpHandlers { + + @Bean + HttpHandler additionalHttpHandler() { + return mock(HttpHandler.class); + } + + } + + @Configuration(proxyBeanMethods = false) + static class ReactiveWebServerCustomization { + + @Bean + WebServerFactoryCustomizer reactiveWebServerCustomizer() { + return (factory) -> factory.setPort(9000); + } + + } + + @Configuration(proxyBeanMethods = false) + static class MockWebServerConfiguration { + + @Bean + MockReactiveWebServerFactory mockReactiveWebServerFactory() { + return new MockReactiveWebServerFactory(); + } + + } + + @Configuration(proxyBeanMethods = false) + static class ForwardedHeaderTransformerConfiguration { + + @Bean + ForwardedHeaderTransformer testForwardedHeaderTransformer() { + return new ForwardedHeaderTransformer(); + } + + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/ReactiveWebServerFactoryCustomizerTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/reactive/ReactiveWebServerFactoryCustomizerTests.java similarity index 94% rename from spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/ReactiveWebServerFactoryCustomizerTests.java rename to spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/reactive/ReactiveWebServerFactoryCustomizerTests.java index 4ec66ec844..026b00a4ec 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/ReactiveWebServerFactoryCustomizerTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/reactive/ReactiveWebServerFactoryCustomizerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.web.reactive; +package org.springframework.boot.autoconfigure.web.server.reactive; import java.net.InetAddress; @@ -24,9 +24,9 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.ssl.DefaultSslBundleRegistry; import org.springframework.boot.ssl.SslBundles; -import org.springframework.boot.web.reactive.server.ConfigurableReactiveWebServerFactory; import org.springframework.boot.web.server.Shutdown; import org.springframework.boot.web.server.Ssl; +import org.springframework.boot.web.server.reactive.ConfigurableReactiveWebServerFactory; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.assertArg; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/reactive/jetty/JettyReactiveWebServerAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/reactive/jetty/JettyReactiveWebServerAutoConfigurationTests.java new file mode 100644 index 0000000000..902f259939 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/reactive/jetty/JettyReactiveWebServerAutoConfigurationTests.java @@ -0,0 +1,116 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.web.server.reactive.jetty; + +import jakarta.websocket.server.ServerContainer; +import org.eclipse.jetty.ee10.servlet.ServletContextHandler; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.handler.StatisticsHandler; +import org.junit.jupiter.api.Test; + +import org.springframework.boot.autoconfigure.web.server.reactive.AbstractReactiveWebServerAutoConfigurationTests; +import org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext; +import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.jetty.JettyServerCustomizer; +import org.springframework.boot.web.server.jetty.JettyWebServer; +import org.springframework.boot.web.server.reactive.jetty.JettyReactiveWebServerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link JettyReactiveWebServerAutoConfiguration}. + * + * @author Brian Clozel + * @author Raheela Aslam + * @author Madhura Bhave + * @author Scott Frederick + */ +class JettyReactiveWebServerAutoConfigurationTests extends AbstractReactiveWebServerAutoConfigurationTests { + + JettyReactiveWebServerAutoConfigurationTests() { + super(JettyReactiveWebServerAutoConfiguration.class); + } + + @Test + void jettyServerCustomizerBeanIsAddedToFactory() { + this.serverRunner.withUserConfiguration(JettyServerCustomizerConfiguration.class).run((context) -> { + JettyReactiveWebServerFactory factory = context.getBean(JettyReactiveWebServerFactory.class); + assertThat(factory.getServerCustomizers()) + .contains(context.getBean("serverCustomizer", JettyServerCustomizer.class)); + }); + } + + @Test + void jettyServerCustomizerRegisteredAsBeanAndViaFactoryIsOnlyCalledOnce() { + this.serverRunner.withUserConfiguration(DoubleRegistrationJettyServerCustomizerConfiguration.class) + .run((context) -> { + JettyReactiveWebServerFactory factory = context.getBean(JettyReactiveWebServerFactory.class); + JettyServerCustomizer customizer = context.getBean("serverCustomizer", JettyServerCustomizer.class); + assertThat(factory.getServerCustomizers()).contains(customizer); + then(customizer).should().customize(any(Server.class)); + }); + } + + @Test + void webSocketServerContainerIsAvailableFromServletContext() { + this.serverRunner.run((context) -> { + WebServer webServer = ((ReactiveWebServerApplicationContext) context.getSourceApplicationContext()) + .getWebServer(); + ServletContextHandler servletContextHandler = (ServletContextHandler) ((StatisticsHandler) ((JettyWebServer) webServer) + .getServer() + .getHandler()).getHandler(); + Object serverContainer = servletContextHandler.getContext() + .getAttribute("jakarta.websocket.server.ServerContainer"); + assertThat(serverContainer).isInstanceOf(ServerContainer.class); + }); + } + + @Configuration(proxyBeanMethods = false) + static class JettyServerCustomizerConfiguration { + + @Bean + JettyServerCustomizer serverCustomizer() { + return (server) -> { + }; + } + + } + + @Configuration(proxyBeanMethods = false) + static class DoubleRegistrationJettyServerCustomizerConfiguration { + + private final JettyServerCustomizer customizer = mock(JettyServerCustomizer.class); + + @Bean + JettyServerCustomizer serverCustomizer() { + return this.customizer; + } + + @Bean + WebServerFactoryCustomizer jettyCustomizer() { + return (jetty) -> jetty.addServerCustomizers(this.customizer); + } + + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/reactive/netty/NettyReactiveWebServerAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/reactive/netty/NettyReactiveWebServerAutoConfigurationTests.java new file mode 100644 index 0000000000..1c7e0615da --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/reactive/netty/NettyReactiveWebServerAutoConfigurationTests.java @@ -0,0 +1,101 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.web.server.reactive.netty; + +import org.junit.jupiter.api.Test; +import reactor.netty.http.server.HttpServer; + +import org.springframework.boot.autoconfigure.web.server.reactive.AbstractReactiveWebServerAutoConfigurationTests; +import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.reactive.netty.NettyReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.netty.NettyServerCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link NettyReactiveWebServerAutoConfiguration}. + * + * @author Brian Clozel + * @author Raheela Aslam + * @author Madhura Bhave + * @author Scott Frederick + */ +// @DirtiesUrlFactories +class NettyReactiveWebServerAutoConfigurationTests extends AbstractReactiveWebServerAutoConfigurationTests { + + NettyReactiveWebServerAutoConfigurationTests() { + super(NettyReactiveWebServerAutoConfiguration.class); + } + + @Test + void nettyServerCustomizerBeanIsAddedToFactory() { + this.serverRunner.withUserConfiguration(NettyServerCustomizerConfiguration.class).run((context) -> { + NettyReactiveWebServerFactory factory = context.getBean(NettyReactiveWebServerFactory.class); + assertThat(factory.getServerCustomizers()) + .contains(context.getBean("serverCustomizer", NettyServerCustomizer.class)); + }); + } + + @Test + void nettyServerCustomizerRegisteredAsBeanAndViaFactoryIsOnlyCalledOnce() { + this.serverRunner.withUserConfiguration(DoubleRegistrationNettyServerCustomizerConfiguration.class) + .run((context) -> { + NettyReactiveWebServerFactory factory = context.getBean(NettyReactiveWebServerFactory.class); + NettyServerCustomizer customizer = context.getBean("serverCustomizer", NettyServerCustomizer.class); + assertThat(factory.getServerCustomizers()).contains(customizer); + then(customizer).should().apply(any(HttpServer.class)); + }); + } + + @Configuration(proxyBeanMethods = false) + static class NettyServerCustomizerConfiguration { + + @Bean + NettyServerCustomizer serverCustomizer() { + return (server) -> server; + } + + } + + @Configuration(proxyBeanMethods = false) + static class DoubleRegistrationNettyServerCustomizerConfiguration { + + private final NettyServerCustomizer customizer = mock(NettyServerCustomizer.class); + + DoubleRegistrationNettyServerCustomizerConfiguration() { + given(this.customizer.apply(any(HttpServer.class))).willAnswer((invocation) -> invocation.getArgument(0)); + } + + @Bean + NettyServerCustomizer serverCustomizer() { + return this.customizer; + } + + @Bean + WebServerFactoryCustomizer nettyCustomizer() { + return (netty) -> netty.addServerCustomizers(this.customizer); + } + + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/NettyWebServerFactoryCustomizerTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/reactive/netty/NettyReactiveWebServerFactoryCustomizerTests.java similarity index 93% rename from spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/NettyWebServerFactoryCustomizerTests.java rename to spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/reactive/netty/NettyReactiveWebServerFactoryCustomizerTests.java index 7004679435..9caee399e3 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/NettyWebServerFactoryCustomizerTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/reactive/netty/NettyReactiveWebServerFactoryCustomizerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.web.embedded; +package org.springframework.boot.autoconfigure.web.server.reactive.netty; import java.time.Duration; import java.util.Map; @@ -32,8 +32,8 @@ import reactor.netty.http.server.HttpServer; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.context.properties.source.ConfigurationPropertySources; -import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; -import org.springframework.boot.web.embedded.netty.NettyServerCustomizer; +import org.springframework.boot.web.server.reactive.netty.NettyReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.netty.NettyServerCustomizer; import org.springframework.mock.env.MockEnvironment; import org.springframework.util.unit.DataSize; @@ -45,20 +45,20 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; /** - * Tests for {@link NettyWebServerFactoryCustomizer}. + * Tests for {@link NettyReactiveWebServerFactoryCustomizer}. * * @author Brian Clozel * @author Artsiom Yudovin * @author Leo Li */ @ExtendWith(MockitoExtension.class) -class NettyWebServerFactoryCustomizerTests { +class NettyReactiveWebServerFactoryCustomizerTests { private MockEnvironment environment; private ServerProperties serverProperties; - private NettyWebServerFactoryCustomizer customizer; + private NettyReactiveWebServerFactoryCustomizer customizer; @Captor private ArgumentCaptor customizerCaptor; @@ -68,7 +68,7 @@ class NettyWebServerFactoryCustomizerTests { this.environment = new MockEnvironment(); this.serverProperties = new ServerProperties(); ConfigurationPropertySources.attach(this.environment); - this.customizer = new NettyWebServerFactoryCustomizer(this.environment, this.serverProperties); + this.customizer = new NettyReactiveWebServerFactoryCustomizer(this.environment, this.serverProperties); } @Test diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/reactive/tomcat/TomcatReactiveWebServerAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/reactive/tomcat/TomcatReactiveWebServerAutoConfigurationTests.java new file mode 100644 index 0000000000..13b961d639 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/reactive/tomcat/TomcatReactiveWebServerAutoConfigurationTests.java @@ -0,0 +1,227 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.web.server.reactive.tomcat; + +import jakarta.servlet.ServletContext; +import jakarta.websocket.server.ServerContainer; +import org.apache.catalina.Container; +import org.apache.catalina.Context; +import org.apache.catalina.connector.Connector; +import org.apache.catalina.startup.Tomcat; +import org.junit.jupiter.api.Test; + +import org.springframework.boot.autoconfigure.web.server.reactive.AbstractReactiveWebServerAutoConfigurationTests; +import org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext; +import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.reactive.tomcat.TomcatReactiveWebServerFactory; +import org.springframework.boot.web.server.tomcat.TomcatConnectorCustomizer; +import org.springframework.boot.web.server.tomcat.TomcatContextCustomizer; +import org.springframework.boot.web.server.tomcat.TomcatProtocolHandlerCustomizer; +import org.springframework.boot.web.server.tomcat.TomcatWebServer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link TomcatReactiveWebServerAutoConfiguration}. + * + * @author Brian Clozel + * @author Raheela Aslam + * @author Madhura Bhave + * @author Scott Frederick + */ +class TomcatReactiveWebServerAutoConfigurationTests extends AbstractReactiveWebServerAutoConfigurationTests { + + TomcatReactiveWebServerAutoConfigurationTests() { + super(TomcatReactiveWebServerAutoConfiguration.class); + } + + @Test + void tomcatConnectorCustomizerBeanIsAddedToFactory() { + this.serverRunner.withUserConfiguration(TomcatConnectorCustomizerConfiguration.class).run((context) -> { + TomcatReactiveWebServerFactory factory = context.getBean(TomcatReactiveWebServerFactory.class); + TomcatConnectorCustomizer customizer = context.getBean("connectorCustomizer", + TomcatConnectorCustomizer.class); + assertThat(factory.getConnectorCustomizers()).contains(customizer); + then(customizer).should().customize(any(Connector.class)); + }); + } + + @Test + void tomcatConnectorCustomizerRegisteredAsBeanAndViaFactoryIsOnlyCalledOnce() { + this.serverRunner.withUserConfiguration(DoubleRegistrationTomcatConnectorCustomizerConfiguration.class) + .run((context) -> { + TomcatReactiveWebServerFactory factory = context.getBean(TomcatReactiveWebServerFactory.class); + TomcatConnectorCustomizer customizer = context.getBean("connectorCustomizer", + TomcatConnectorCustomizer.class); + assertThat(factory.getConnectorCustomizers()).contains(customizer); + then(customizer).should().customize(any(Connector.class)); + }); + } + + @Test + void tomcatContextCustomizerBeanIsAddedToFactory() { + this.serverRunner.withUserConfiguration(TomcatContextCustomizerConfiguration.class).run((context) -> { + TomcatReactiveWebServerFactory factory = context.getBean(TomcatReactiveWebServerFactory.class); + TomcatContextCustomizer customizer = context.getBean("contextCustomizer", TomcatContextCustomizer.class); + assertThat(factory.getContextCustomizers()).contains(customizer); + then(customizer).should().customize(any(Context.class)); + }); + } + + @Test + void tomcatContextCustomizerRegisteredAsBeanAndViaFactoryIsOnlyCalledOnce() { + this.serverRunner.withUserConfiguration(DoubleRegistrationTomcatContextCustomizerConfiguration.class) + .run((context) -> { + TomcatReactiveWebServerFactory factory = context.getBean(TomcatReactiveWebServerFactory.class); + TomcatContextCustomizer customizer = context.getBean("contextCustomizer", + TomcatContextCustomizer.class); + assertThat(factory.getContextCustomizers()).contains(customizer); + then(customizer).should().customize(any(Context.class)); + }); + } + + @Test + void tomcatProtocolHandlerCustomizerBeanIsAddedToFactory() { + this.serverRunner.withUserConfiguration(TomcatProtocolHandlerCustomizerConfiguration.class).run((context) -> { + TomcatReactiveWebServerFactory factory = context.getBean(TomcatReactiveWebServerFactory.class); + TomcatProtocolHandlerCustomizer customizer = context.getBean("protocolHandlerCustomizer", + TomcatProtocolHandlerCustomizer.class); + assertThat(factory.getProtocolHandlerCustomizers()).contains(customizer); + then(customizer).should().customize(any()); + }); + } + + @Test + void tomcatProtocolHandlerCustomizerRegisteredAsBeanAndViaFactoryIsOnlyCalledOnce() { + this.serverRunner.withUserConfiguration(DoubleRegistrationTomcatProtocolHandlerCustomizerConfiguration.class) + .run((context) -> { + TomcatReactiveWebServerFactory factory = context.getBean(TomcatReactiveWebServerFactory.class); + TomcatProtocolHandlerCustomizer customizer = context.getBean("protocolHandlerCustomizer", + TomcatProtocolHandlerCustomizer.class); + assertThat(factory.getProtocolHandlerCustomizers()).contains(customizer); + then(customizer).should().customize(any()); + }); + } + + @Test + void webSocketServerContainerIsAvailableFromServletContext() { + this.serverRunner.run((context) -> { + WebServer webServer = ((ReactiveWebServerApplicationContext) context.getSourceApplicationContext()) + .getWebServer(); + ServletContext servletContext = findContext(((TomcatWebServer) webServer).getTomcat()).getServletContext(); + Object serverContainer = servletContext.getAttribute("jakarta.websocket.server.ServerContainer"); + assertThat(serverContainer).isInstanceOf(ServerContainer.class); + }); + } + + private static Context findContext(Tomcat tomcat) { + for (Container child : tomcat.getHost().findChildren()) { + if (child instanceof Context context) { + return context; + } + } + throw new IllegalStateException("The Host does not contain a Context"); + } + + @Configuration(proxyBeanMethods = false) + static class TomcatConnectorCustomizerConfiguration { + + @Bean + TomcatConnectorCustomizer connectorCustomizer() { + return mock(TomcatConnectorCustomizer.class); + } + + } + + @Configuration(proxyBeanMethods = false) + static class DoubleRegistrationTomcatConnectorCustomizerConfiguration { + + private final TomcatConnectorCustomizer customizer = mock(TomcatConnectorCustomizer.class); + + @Bean + TomcatConnectorCustomizer connectorCustomizer() { + return this.customizer; + } + + @Bean + WebServerFactoryCustomizer tomcatCustomizer() { + return (tomcat) -> tomcat.addConnectorCustomizers(this.customizer); + } + + } + + @Configuration(proxyBeanMethods = false) + static class TomcatContextCustomizerConfiguration { + + @Bean + TomcatContextCustomizer contextCustomizer() { + return mock(TomcatContextCustomizer.class); + } + + } + + @Configuration(proxyBeanMethods = false) + static class DoubleRegistrationTomcatContextCustomizerConfiguration { + + private final TomcatContextCustomizer customizer = mock(TomcatContextCustomizer.class); + + @Bean + TomcatContextCustomizer contextCustomizer() { + return this.customizer; + } + + @Bean + WebServerFactoryCustomizer tomcatCustomizer() { + return (tomcat) -> tomcat.addContextCustomizers(this.customizer); + } + + } + + @Configuration(proxyBeanMethods = false) + static class TomcatProtocolHandlerCustomizerConfiguration { + + @Bean + TomcatProtocolHandlerCustomizer protocolHandlerCustomizer() { + return mock(TomcatProtocolHandlerCustomizer.class); + } + + } + + @Configuration(proxyBeanMethods = false) + static class DoubleRegistrationTomcatProtocolHandlerCustomizerConfiguration { + + private final TomcatProtocolHandlerCustomizer customizer = mock(TomcatProtocolHandlerCustomizer.class); + + @Bean + TomcatProtocolHandlerCustomizer protocolHandlerCustomizer() { + return this.customizer; + } + + @Bean + WebServerFactoryCustomizer tomcatCustomizer() { + return (tomcat) -> tomcat.addProtocolHandlerCustomizers(this.customizer); + } + + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/reactive/undertow/UndertowReactiveWebServerAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/reactive/undertow/UndertowReactiveWebServerAutoConfigurationTests.java new file mode 100644 index 0000000000..37584f23e4 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/reactive/undertow/UndertowReactiveWebServerAutoConfigurationTests.java @@ -0,0 +1,109 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.web.server.reactive.undertow; + +import io.undertow.Undertow.Builder; +import org.junit.jupiter.api.Test; + +import org.springframework.boot.autoconfigure.web.server.reactive.AbstractReactiveWebServerAutoConfigurationTests; +import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.reactive.undertow.UndertowReactiveWebServerFactory; +import org.springframework.boot.web.server.servlet.undertow.UndertowDeploymentInfoCustomizer; +import org.springframework.boot.web.server.undertow.UndertowBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link UndertowReactiveWebServerAutoConfiguration}. + * + * @author Brian Clozel + * @author Raheela Aslam + * @author Madhura Bhave + * @author Scott Frederick + */ +class UndertowReactiveWebServerAutoConfigurationTests extends AbstractReactiveWebServerAutoConfigurationTests { + + UndertowReactiveWebServerAutoConfigurationTests() { + super(UndertowReactiveWebServerAutoConfiguration.class); + } + + @Test + void undertowBuilderCustomizerBeanIsAddedToFactory() { + this.serverRunner.withUserConfiguration(UndertowBuilderCustomizerConfiguration.class).run((context) -> { + UndertowReactiveWebServerFactory factory = context.getBean(UndertowReactiveWebServerFactory.class); + assertThat(factory.getBuilderCustomizers()) + .contains(context.getBean("builderCustomizer", UndertowBuilderCustomizer.class)); + }); + } + + @Test + void undertowBuilderCustomizerRegisteredAsBeanAndViaFactoryIsOnlyCalledOnce() { + this.serverRunner.withUserConfiguration(DoubleRegistrationUndertowBuilderCustomizerConfiguration.class) + .run((context) -> { + UndertowReactiveWebServerFactory factory = context.getBean(UndertowReactiveWebServerFactory.class); + UndertowBuilderCustomizer customizer = context.getBean("builderCustomizer", + UndertowBuilderCustomizer.class); + assertThat(factory.getBuilderCustomizers()).contains(customizer); + then(customizer).should().customize(any(Builder.class)); + }); + } + + @Configuration(proxyBeanMethods = false) + static class UndertowBuilderCustomizerConfiguration { + + @Bean + UndertowBuilderCustomizer builderCustomizer() { + return (builder) -> { + }; + } + + } + + @Configuration(proxyBeanMethods = false) + static class DoubleRegistrationUndertowBuilderCustomizerConfiguration { + + private final UndertowBuilderCustomizer customizer = mock(UndertowBuilderCustomizer.class); + + @Bean + UndertowBuilderCustomizer builderCustomizer() { + return this.customizer; + } + + @Bean + WebServerFactoryCustomizer undertowCustomizer() { + return (undertow) -> undertow.addBuilderCustomizers(this.customizer); + } + + } + + @Configuration(proxyBeanMethods = false) + static class UndertowDeploymentInfoCustomizerConfiguration { + + @Bean + UndertowDeploymentInfoCustomizer deploymentInfoCustomizer() { + return (deploymentInfo) -> { + }; + } + + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/servlet/AbstractServletWebServerAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/servlet/AbstractServletWebServerAutoConfigurationTests.java new file mode 100644 index 0000000000..00e48085eb --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/servlet/AbstractServletWebServerAutoConfigurationTests.java @@ -0,0 +1,284 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.web.server.servlet; + +import java.io.IOException; + +import jakarta.servlet.DispatcherType; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.websocket.server.ServerContainer; +import jakarta.websocket.server.ServerEndpoint; +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.boot.test.context.runner.WebApplicationContextRunner; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.context.WebServerApplicationContext; +import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.servlet.ConfigurableServletWebServerFactory; +import org.springframework.boot.web.server.servlet.CookieSameSiteSupplier; +import org.springframework.boot.web.server.servlet.MockServletWebServerFactory; +import org.springframework.boot.web.server.servlet.ServletContextInitializer; +import org.springframework.boot.web.server.servlet.ServletWebServerFactory; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.Ordered; +import org.springframework.http.HttpStatus; +import org.springframework.http.RequestEntity; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.ForwardedHeaderFilter; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Base class for testing sub-classes of {@link ServletWebServerConfiguration}. + * + * @author Dave Syer + * @author Phillip Webb + * @author Stephane Nicoll + * @author Raheela Aslam + * @author Madhura Bhave + */ +public abstract class AbstractServletWebServerAutoConfigurationTests { + + private final WebApplicationContextRunner mockServerRunner; + + protected final WebApplicationContextRunner serverRunner; + + protected AbstractServletWebServerAutoConfigurationTests(Class serverAutoConfiguration) { + WebApplicationContextRunner common = new WebApplicationContextRunner( + AnnotationConfigServletWebServerApplicationContext::new) + .withConfiguration(AutoConfigurations.of(serverAutoConfiguration)); + this.serverRunner = common.withPropertyValues("server.port=0"); + this.mockServerRunner = common.withUserConfiguration(MockWebServerConfiguration.class); + } + + @Test + void createFromConfigClass() { + this.mockServerRunner + .run((context) -> assertThat(context).hasSingleBean(ServletWebServerFactoryCustomizer.class)); + } + + @Test + void webServerHasNoServletContext() { + this.mockServerRunner.withUserConfiguration(EnsureWebServerHasNoServletContext.class) + .run((context) -> assertThat(context).hasNotFailed()); + } + + @Test + void webServerFactoryCustomizerBeansAreCalledToCustomizeWebServerFactory() { + this.mockServerRunner + .withBean(WebServerFactoryCustomizer.class, + () -> (WebServerFactoryCustomizer) (factory) -> factory + .setPort(9000)) + .run((context) -> assertThat(context.getBean(MockServletWebServerFactory.class).getPort()).isEqualTo(9000)); + } + + @Test + void initParametersAreConfiguredOnTheServletContext() { + this.mockServerRunner + .withPropertyValues("server.servlet.context-parameters.a:alpha", + "server.servlet.context-parameters.b:bravo") + .run((context) -> { + ServletContext servletContext = context.getServletContext(); + assertThat(servletContext.getInitParameter("a")).isEqualTo("alpha"); + assertThat(servletContext.getInitParameter("b")).isEqualTo("bravo"); + }); + } + + @Test + void forwardedHeaderFilterShouldBeConfigured() { + this.mockServerRunner.withPropertyValues("server.forward-headers-strategy=framework").run((context) -> { + assertThat(context).hasSingleBean(FilterRegistrationBean.class); + Filter filter = context.getBean(FilterRegistrationBean.class).getFilter(); + assertThat(filter).isInstanceOf(ForwardedHeaderFilter.class); + assertThat(filter).extracting("relativeRedirects").isEqualTo(false); + }); + } + + @Test + void forwardedHeaderFilterWhenStrategyNotFilterShouldNotBeConfigured() { + this.mockServerRunner.withPropertyValues("server.forward-headers-strategy=native") + .run((context) -> assertThat(context).doesNotHaveBean(FilterRegistrationBean.class)); + } + + @Test + void forwardedHeaderFilterWhenFilterAlreadyRegisteredShouldBackOff() { + this.mockServerRunner.withUserConfiguration(ForwardedHeaderFilterConfiguration.class) + .withPropertyValues("server.forward-headers-strategy=framework") + .run((context) -> assertThat(context).hasSingleBean(FilterRegistrationBean.class)); + } + + @Test + void cookieSameSiteSuppliersAreApplied() { + this.mockServerRunner.withUserConfiguration(CookieSameSiteSupplierConfiguration.class).run((context) -> { + ConfigurableServletWebServerFactory webServerFactory = context + .getBean(ConfigurableServletWebServerFactory.class); + assertThat(webServerFactory.getSettings().getCookieSameSiteSuppliers()).hasSize(2); + }); + } + + @Test + void webSocketServerContainerIsAvailableFromServletContext() { + this.serverRunner.run((context) -> { + Object serverContainer = context.getServletContext() + .getAttribute("jakarta.websocket.server.ServerContainer"); + assertThat(serverContainer).isInstanceOf(ServerContainer.class); + }); + } + + @Test + void webSocketUpgradeDoesNotPreventAFilterFromRejectingTheRequest() { + this.serverRunner + .withBean("testEndpointRegistrar", ServletContextInitializer.class, () -> TestEndpoint::register) + .withUserConfiguration(UnauthorizedFilterConfiguration.class) + .run((context) -> { + TestEndpoint.register(context.getServletContext()); + WebServer webServer = ((WebServerApplicationContext) context.getSourceApplicationContext()) + .getWebServer(); + int port = webServer.getPort(); + TestRestTemplate rest = new TestRestTemplate(); + RequestEntity request = RequestEntity.get("http://localhost:" + port) + .header("Upgrade", "websocket") + .header("Connection", "upgrade") + .header("Sec-WebSocket-Version", "13") + .header("Sec-WebSocket-Key", "key") + .build(); + ResponseEntity response = rest.exchange(request, Void.class); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); + }); + } + + @Configuration(proxyBeanMethods = false) + @ConditionalOnExpression("true") + static class MockWebServerConfiguration { + + @Bean + ServletWebServerFactory webServerFactory() { + return new MockServletWebServerFactory(); + } + + } + + @Component + static class EnsureWebServerHasNoServletContext implements BeanPostProcessor { + + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) { + if (bean instanceof ConfigurableServletWebServerFactory) { + MockServletWebServerFactory webServerFactory = (MockServletWebServerFactory) bean; + assertThat(webServerFactory.getServletContext()).isNull(); + } + return bean; + } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) { + return bean; + } + + } + + @Configuration(proxyBeanMethods = false) + static class ForwardedHeaderFilterConfiguration { + + @Bean + FilterRegistrationBean testForwardedHeaderFilter() { + ForwardedHeaderFilter filter = new ForwardedHeaderFilter(); + return new FilterRegistrationBean<>(filter); + } + + } + + @Configuration(proxyBeanMethods = false) + static class CookieSameSiteSupplierConfiguration { + + @Bean + CookieSameSiteSupplier cookieSameSiteSupplier1() { + return CookieSameSiteSupplier.ofLax().whenHasName("test1"); + } + + @Bean + CookieSameSiteSupplier cookieSameSiteSupplier2() { + return CookieSameSiteSupplier.ofNone().whenHasName("test2"); + } + + } + + @ServerEndpoint("/") + public static class TestEndpoint { + + static void register(ServletContext context) { + try { + ServerContainer serverContainer = (ServerContainer) context + .getAttribute("jakarta.websocket.server.ServerContainer"); + if (serverContainer != null) { + serverContainer.addEndpoint(TestEndpoint.class); + } + } + catch (Exception ex) { + // Continue + } + } + + } + + @Configuration(proxyBeanMethods = false) + static class UnauthorizedFilterConfiguration { + + @Bean + FilterRegistrationBean unauthorizedFilter() { + FilterRegistrationBean registration = new FilterRegistrationBean<>(new Filter() { + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + ((HttpServletResponse) response).sendError(HttpStatus.UNAUTHORIZED.value()); + } + + }); + registration.setOrder(Ordered.HIGHEST_PRECEDENCE); + registration.addUrlPatterns("/*"); + registration.setDispatcherTypes(DispatcherType.REQUEST); + return registration; + } + + @Bean + ServletRegistrationBean basicServlet() { + ServletRegistrationBean registration = new ServletRegistrationBean<>(new HttpServlet() { + }); + registration.addUrlMappings("/"); + return registration; + } + + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryCustomizerTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/servlet/ServletWebServerFactoryCustomizerTests.java similarity index 97% rename from spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryCustomizerTests.java rename to spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/servlet/ServletWebServerFactoryCustomizerTests.java index 3a9d8843b2..d7e7685fc4 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryCustomizerTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/servlet/ServletWebServerFactoryCustomizerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.web.servlet; +package org.springframework.boot.autoconfigure.web.server.servlet; import java.io.File; import java.nio.charset.StandardCharsets; @@ -35,8 +35,8 @@ import org.springframework.boot.web.server.Cookie; import org.springframework.boot.web.server.MimeMappings; import org.springframework.boot.web.server.Shutdown; import org.springframework.boot.web.server.Ssl; -import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; -import org.springframework.boot.web.servlet.server.Jsp; +import org.springframework.boot.web.server.servlet.ConfigurableServletWebServerFactory; +import org.springframework.boot.web.server.servlet.Jsp; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerServletContextListenerTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/servlet/ServletWebServerServletContextListenerTests.java similarity index 90% rename from spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerServletContextListenerTests.java rename to spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/servlet/ServletWebServerServletContextListenerTests.java index ec52ceab9c..0977016a30 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerServletContextListenerTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/servlet/ServletWebServerServletContextListenerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.web.servlet; +package org.springframework.boot.autoconfigure.web.server.servlet; import java.util.stream.Stream; @@ -26,13 +26,13 @@ import org.junit.jupiter.params.provider.MethodSource; import org.springframework.boot.testsupport.classpath.ForkedClassPath; import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories; -import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; -import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory; import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.servlet.ServletWebServerFactory; +import org.springframework.boot.web.server.servlet.jetty.JettyServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.servlet.undertow.UndertowServletWebServerFactory; import org.springframework.boot.web.servlet.ServletListenerRegistrationBean; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; -import org.springframework.boot.web.servlet.server.ServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/servlet/jetty/JettyServletWebServerAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/servlet/jetty/JettyServletWebServerAutoConfigurationTests.java new file mode 100644 index 0000000000..561e1200b7 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/servlet/jetty/JettyServletWebServerAutoConfigurationTests.java @@ -0,0 +1,148 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.web.server.servlet.jetty; + +import java.util.Map; + +import jakarta.servlet.Filter; +import org.eclipse.jetty.ee10.websocket.servlet.WebSocketUpgradeFilter; +import org.eclipse.jetty.server.Server; +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.boot.autoconfigure.web.server.servlet.AbstractServletWebServerAutoConfigurationTests; +import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.jetty.JettyServerCustomizer; +import org.springframework.boot.web.server.servlet.ServletContextInitializer; +import org.springframework.boot.web.server.servlet.jetty.JettyServletWebServerFactory; +import org.springframework.boot.web.servlet.AbstractFilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.mock; + +/** + * Base class for testing sub-classes of {@link JettyServletWebServerAutoConfiguration}. + * + * @author Dave Syer + * @author Phillip Webb + * @author Stephane Nicoll + * @author Raheela Aslam + * @author Madhura Bhave + */ +class JettyServletWebServerAutoConfigurationTests extends AbstractServletWebServerAutoConfigurationTests { + + protected JettyServletWebServerAutoConfigurationTests() { + super(JettyServletWebServerAutoConfiguration.class); + } + + @Test + void jettyServerCustomizerBeanIsAddedToFactory() { + this.serverRunner.withUserConfiguration(JettyServerCustomizerConfiguration.class).run((context) -> { + JettyServletWebServerFactory factory = context.getBean(JettyServletWebServerFactory.class); + assertThat(factory.getServerCustomizers()) + .contains(context.getBean("serverCustomizer", JettyServerCustomizer.class)); + }); + } + + @Test + void jettyServerCustomizerRegisteredAsBeanAndViaFactoryIsOnlyCalledOnce() { + this.serverRunner.withUserConfiguration(DoubleRegistrationJettyServerCustomizerConfiguration.class) + .run((context) -> { + JettyServletWebServerFactory factory = context.getBean(JettyServletWebServerFactory.class); + JettyServerCustomizer customizer = context.getBean("serverCustomizer", JettyServerCustomizer.class); + assertThat(factory.getServerCustomizers()).contains(customizer); + then(customizer).should().customize(any(Server.class)); + }); + } + + @Test + void jettyWebSocketUpgradeFilterIsAddedToServletContex() { + this.serverRunner.run((context) -> assertThat( + context.getServletContext().getFilterRegistration(WebSocketUpgradeFilter.class.getName())) + .isNotNull()); + } + + @Test + @SuppressWarnings("rawtypes") + void jettyWebSocketUpgradeFilterIsNotExposedAsABean() { + this.serverRunner.run((context) -> { + Map filters = context.getBeansOfType(Filter.class); + assertThat(filters.values()).noneMatch(WebSocketUpgradeFilter.class::isInstance); + Map filterRegistrations = context + .getBeansOfType(AbstractFilterRegistrationBean.class); + assertThat(filterRegistrations.values()).extracting(AbstractFilterRegistrationBean::getFilter) + .noneMatch(WebSocketUpgradeFilter.class::isInstance); + }); + } + + @Test + void jettyWebSocketUpgradeFilterServletContextInitializerBacksOffWhenBeanWithSameNameIsDefined() { + this.serverRunner + .withUserConfiguration(CustomWebSocketUpgradeFilterServletContextInitializerConfiguration.class) + .run((context) -> { + BeanDefinition definition = context.getBeanFactory() + .getBeanDefinition("websocketUpgradeFilterServletContextInitializer"); + assertThat(definition.getFactoryBeanName()) + .contains("CustomWebSocketUpgradeFilterServletContextInitializerConfiguration"); + }); + } + + @Configuration(proxyBeanMethods = false) + static class JettyServerCustomizerConfiguration { + + @Bean + JettyServerCustomizer serverCustomizer() { + return (server) -> { + }; + } + + } + + @Configuration(proxyBeanMethods = false) + static class DoubleRegistrationJettyServerCustomizerConfiguration { + + private final JettyServerCustomizer customizer = mock(JettyServerCustomizer.class); + + @Bean + JettyServerCustomizer serverCustomizer() { + return this.customizer; + } + + @Bean + WebServerFactoryCustomizer jettyCustomizer() { + return (jetty) -> jetty.addServerCustomizers(this.customizer); + } + + } + + @Configuration(proxyBeanMethods = false) + static class CustomWebSocketUpgradeFilterServletContextInitializerConfiguration { + + @Bean + ServletContextInitializer websocketUpgradeFilterServletContextInitializer() { + return (servletContext) -> { + + }; + } + + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/servlet/tomcat/TomcatServletWebServerAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/servlet/tomcat/TomcatServletWebServerAutoConfigurationTests.java new file mode 100644 index 0000000000..150da43e94 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/servlet/tomcat/TomcatServletWebServerAutoConfigurationTests.java @@ -0,0 +1,228 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.web.server.servlet.tomcat; + +import jakarta.servlet.Filter; +import org.apache.catalina.Context; +import org.apache.catalina.connector.Connector; +import org.junit.jupiter.api.Test; + +import org.springframework.boot.autoconfigure.web.server.servlet.AbstractServletWebServerAutoConfigurationTests; +import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.tomcat.TomcatConnectorCustomizer; +import org.springframework.boot.web.server.tomcat.TomcatContextCustomizer; +import org.springframework.boot.web.server.tomcat.TomcatProtocolHandlerCustomizer; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.filter.ForwardedHeaderFilter; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link TomcatServletWebServerAutoConfiguration}. + * + * @author Dave Syer + * @author Phillip Webb + * @author Stephane Nicoll + * @author Raheela Aslam + * @author Madhura Bhave + */ +class TomcatServletWebServerAutoConfigurationTests extends AbstractServletWebServerAutoConfigurationTests { + + TomcatServletWebServerAutoConfigurationTests() { + super(TomcatServletWebServerAutoConfiguration.class); + } + + @Test + void tomcatConnectorCustomizerBeanIsAddedToFactory() { + this.serverRunner.withUserConfiguration(TomcatConnectorCustomizerConfiguration.class).run((context) -> { + TomcatServletWebServerFactory factory = context.getBean(TomcatServletWebServerFactory.class); + TomcatConnectorCustomizer customizer = context.getBean("connectorCustomizer", + TomcatConnectorCustomizer.class); + assertThat(factory.getConnectorCustomizers()).contains(customizer); + then(customizer).should().customize(any(Connector.class)); + }); + } + + @Test + void tomcatConnectorCustomizerRegisteredAsBeanAndViaFactoryIsOnlyCalledOnce() { + this.serverRunner.withUserConfiguration(DoubleRegistrationTomcatConnectorCustomizerConfiguration.class) + .run((context) -> { + TomcatServletWebServerFactory factory = context.getBean(TomcatServletWebServerFactory.class); + TomcatConnectorCustomizer customizer = context.getBean("connectorCustomizer", + TomcatConnectorCustomizer.class); + assertThat(factory.getConnectorCustomizers()).contains(customizer); + then(customizer).should().customize(any(Connector.class)); + }); + } + + @Test + void tomcatContextCustomizerBeanIsAddedToFactory() { + this.serverRunner.withUserConfiguration(TomcatContextCustomizerConfiguration.class).run((context) -> { + TomcatServletWebServerFactory factory = context.getBean(TomcatServletWebServerFactory.class); + TomcatContextCustomizer customizer = context.getBean("contextCustomizer", TomcatContextCustomizer.class); + assertThat(factory.getContextCustomizers()).contains(customizer); + then(customizer).should().customize(any(Context.class)); + }); + } + + @Test + void tomcatContextCustomizerRegisteredAsBeanAndViaFactoryIsOnlyCalledOnce() { + this.serverRunner.withUserConfiguration(DoubleRegistrationTomcatContextCustomizerConfiguration.class) + .run((context) -> { + TomcatServletWebServerFactory factory = context.getBean(TomcatServletWebServerFactory.class); + TomcatContextCustomizer customizer = context.getBean("contextCustomizer", + TomcatContextCustomizer.class); + assertThat(factory.getContextCustomizers()).contains(customizer); + then(customizer).should().customize(any(Context.class)); + }); + } + + @Test + void tomcatProtocolHandlerCustomizerBeanIsAddedToFactory() { + this.serverRunner.withUserConfiguration(TomcatProtocolHandlerCustomizerConfiguration.class).run((context) -> { + TomcatServletWebServerFactory factory = context.getBean(TomcatServletWebServerFactory.class); + TomcatProtocolHandlerCustomizer customizer = context.getBean("protocolHandlerCustomizer", + TomcatProtocolHandlerCustomizer.class); + assertThat(factory.getProtocolHandlerCustomizers()).contains(customizer); + then(customizer).should().customize(any()); + }); + } + + @Test + void tomcatProtocolHandlerCustomizerRegisteredAsBeanAndViaFactoryIsOnlyCalledOnce() { + this.serverRunner.withUserConfiguration(DoubleRegistrationTomcatProtocolHandlerCustomizerConfiguration.class) + .run((context) -> { + TomcatServletWebServerFactory factory = context.getBean(TomcatServletWebServerFactory.class); + TomcatProtocolHandlerCustomizer customizer = context.getBean("protocolHandlerCustomizer", + TomcatProtocolHandlerCustomizer.class); + assertThat(factory.getProtocolHandlerCustomizers()).contains(customizer); + then(customizer).should().customize(any()); + }); + } + + @Test + void whenUsingFrameworkForwardHeadersStrategyAndRelativeRedirectsAreEnabledThenFilterIsConfiguredToUseRelativeRedirects() { + this.serverRunner + .withPropertyValues("server.forward-headers-strategy=framework", + "server.tomcat.use-relative-redirects=true", "server.port=0") + .run((context) -> { + Filter filter = context.getBean(FilterRegistrationBean.class).getFilter(); + assertThat(filter).isInstanceOf(ForwardedHeaderFilter.class); + assertThat(filter).extracting("relativeRedirects").isEqualTo(true); + }); + } + + @Test + void whenUsingFrameworkForwardHeadersStrategyAndNotUsingRelativeRedirectsThenFilterIsNotConfiguredToUseRelativeRedirects() { + this.serverRunner + .withPropertyValues("server.forward-headers-strategy=framework", + "server.tomcat.use-relative-redirects=false", "server.port=0") + .run((context) -> { + Filter filter = context.getBean(FilterRegistrationBean.class).getFilter(); + assertThat(filter).isInstanceOf(ForwardedHeaderFilter.class); + assertThat(filter).extracting("relativeRedirects").isEqualTo(false); + }); + } + + @Configuration(proxyBeanMethods = false) + static class TomcatConnectorCustomizerConfiguration { + + @Bean + TomcatConnectorCustomizer connectorCustomizer() { + return mock(TomcatConnectorCustomizer.class); + } + + } + + @Configuration(proxyBeanMethods = false) + static class DoubleRegistrationTomcatConnectorCustomizerConfiguration { + + private final TomcatConnectorCustomizer customizer = mock(TomcatConnectorCustomizer.class); + + @Bean + TomcatConnectorCustomizer connectorCustomizer() { + return this.customizer; + } + + @Bean + WebServerFactoryCustomizer tomcatCustomizer() { + return (tomcat) -> tomcat.addConnectorCustomizers(this.customizer); + } + + } + + @Configuration(proxyBeanMethods = false) + static class TomcatContextCustomizerConfiguration { + + @Bean + TomcatContextCustomizer contextCustomizer() { + return mock(TomcatContextCustomizer.class); + } + + } + + @Configuration(proxyBeanMethods = false) + static class DoubleRegistrationTomcatContextCustomizerConfiguration { + + private final TomcatContextCustomizer customizer = mock(TomcatContextCustomizer.class); + + @Bean + TomcatContextCustomizer contextCustomizer() { + return this.customizer; + } + + @Bean + WebServerFactoryCustomizer tomcatCustomizer() { + return (tomcat) -> tomcat.addContextCustomizers(this.customizer); + } + + } + + @Configuration(proxyBeanMethods = false) + static class TomcatProtocolHandlerCustomizerConfiguration { + + @Bean + TomcatProtocolHandlerCustomizer protocolHandlerCustomizer() { + return mock(TomcatProtocolHandlerCustomizer.class); + } + + } + + @Configuration(proxyBeanMethods = false) + static class DoubleRegistrationTomcatProtocolHandlerCustomizerConfiguration { + + private final TomcatProtocolHandlerCustomizer customizer = mock(TomcatProtocolHandlerCustomizer.class); + + @Bean + TomcatProtocolHandlerCustomizer protocolHandlerCustomizer() { + return this.customizer; + } + + @Bean + WebServerFactoryCustomizer tomcatCustomizer() { + return (tomcat) -> tomcat.addProtocolHandlerCustomizers(this.customizer); + } + + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/TomcatServletWebServerFactoryCustomizerTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/servlet/tomcat/TomcatServletWebServerFactoryCustomizerTests.java similarity index 93% rename from spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/TomcatServletWebServerFactoryCustomizerTests.java rename to spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/servlet/tomcat/TomcatServletWebServerFactoryCustomizerTests.java index 44a2210e4e..5fe76d994a 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/TomcatServletWebServerFactoryCustomizerTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/servlet/tomcat/TomcatServletWebServerFactoryCustomizerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.web.servlet; +package org.springframework.boot.autoconfigure.web.server.servlet.tomcat; import org.apache.catalina.Context; import org.junit.jupiter.api.BeforeEach; @@ -24,8 +24,8 @@ import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.context.properties.bind.Bindable; import org.springframework.boot.context.properties.bind.Binder; import org.springframework.boot.context.properties.source.ConfigurationPropertySources; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; -import org.springframework.boot.web.embedded.tomcat.TomcatWebServer; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.tomcat.TomcatWebServer; import org.springframework.mock.env.MockEnvironment; import org.springframework.test.context.support.TestPropertySourceUtils; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/servlet/undertow/UndertowServletWebServerAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/servlet/undertow/UndertowServletWebServerAutoConfigurationTests.java new file mode 100644 index 0000000000..e523b93f5c --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/servlet/undertow/UndertowServletWebServerAutoConfigurationTests.java @@ -0,0 +1,159 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.web.server.servlet.undertow; + +import io.undertow.Undertow.Builder; +import io.undertow.servlet.api.DeploymentInfo; +import org.junit.jupiter.api.Test; + +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.autoconfigure.web.server.servlet.AbstractServletWebServerAutoConfigurationTests; +import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.servlet.undertow.UndertowDeploymentInfoCustomizer; +import org.springframework.boot.web.server.servlet.undertow.UndertowServletWebServerFactory; +import org.springframework.boot.web.server.undertow.UndertowBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link UndertowServletWebServerAutoConfiguration}. + * + * @author Dave Syer + * @author Phillip Webb + * @author Stephane Nicoll + * @author Raheela Aslam + * @author Madhura Bhave + */ +// @DirtiesUrlFactories +class UndertowServletWebServerAutoConfigurationTests extends AbstractServletWebServerAutoConfigurationTests { + + UndertowServletWebServerAutoConfigurationTests() { + super(UndertowServletWebServerAutoConfiguration.class); + } + + @Test + void undertowDeploymentInfoCustomizerBeanIsAddedToFactory() { + this.serverRunner.withUserConfiguration(UndertowDeploymentInfoCustomizerConfiguration.class).run((context) -> { + UndertowServletWebServerFactory factory = context.getBean(UndertowServletWebServerFactory.class); + UndertowDeploymentInfoCustomizer customizer = context.getBean("deploymentInfoCustomizer", + UndertowDeploymentInfoCustomizer.class); + assertThat(factory.getDeploymentInfoCustomizers()).contains(customizer); + }); + } + + @Test + void undertowDeploymentInfoCustomizerRegisteredAsBeanAndViaFactoryIsOnlyCalledOnce() { + this.serverRunner.withUserConfiguration(DoubleRegistrationUndertowDeploymentInfoCustomizerConfiguration.class) + .run((context) -> { + UndertowServletWebServerFactory factory = context.getBean(UndertowServletWebServerFactory.class); + UndertowDeploymentInfoCustomizer customizer = context.getBean("deploymentInfoCustomizer", + UndertowDeploymentInfoCustomizer.class); + assertThat(factory.getDeploymentInfoCustomizers()).contains(customizer); + then(customizer).should().customize(any(DeploymentInfo.class)); + }); + } + + @Test + void undertowBuilderCustomizerRegisteredAsBeanAndViaFactoryIsOnlyCalledOnce() { + this.serverRunner.withConfiguration(AutoConfigurations.of(UndertowServletWebServerAutoConfiguration.class)) + .withUserConfiguration(DoubleRegistrationUndertowBuilderCustomizerConfiguration.class) + .run((context) -> { + UndertowServletWebServerFactory factory = context.getBean(UndertowServletWebServerFactory.class); + UndertowBuilderCustomizer customizer = context.getBean("builderCustomizer", + UndertowBuilderCustomizer.class); + assertThat(factory.getBuilderCustomizers()).contains(customizer); + then(customizer).should().customize(any(Builder.class)); + }); + } + + @Test + void undertowBuilderCustomizerBeanIsAddedToFactory() { + this.serverRunner.withUserConfiguration(UndertowBuilderCustomizerConfiguration.class).run((context) -> { + UndertowServletWebServerFactory factory = context.getBean(UndertowServletWebServerFactory.class); + assertThat(factory.getBuilderCustomizers()) + .contains(context.getBean("builderCustomizer", UndertowBuilderCustomizer.class)); + }); + } + + @Test + void undertowServletWebServerFactoryCustomizerIsAutoConfigured() { + this.serverRunner.withUserConfiguration(UndertowBuilderCustomizerConfiguration.class) + .run((context) -> assertThat(context).hasSingleBean(UndertowServletWebServerFactoryCustomizer.class)); + } + + @Configuration(proxyBeanMethods = false) + static class UndertowBuilderCustomizerConfiguration { + + @Bean + UndertowBuilderCustomizer builderCustomizer() { + return (builder) -> { + }; + } + + } + + @Configuration(proxyBeanMethods = false) + static class DoubleRegistrationUndertowBuilderCustomizerConfiguration { + + private final UndertowBuilderCustomizer customizer = mock(UndertowBuilderCustomizer.class); + + @Bean + UndertowBuilderCustomizer builderCustomizer() { + return this.customizer; + } + + @Bean + WebServerFactoryCustomizer undertowCustomizer() { + return (undertow) -> undertow.addBuilderCustomizers(this.customizer); + } + + } + + @Configuration(proxyBeanMethods = false) + static class UndertowDeploymentInfoCustomizerConfiguration { + + @Bean + UndertowDeploymentInfoCustomizer deploymentInfoCustomizer() { + return (deploymentInfo) -> { + }; + } + + } + + @Configuration(proxyBeanMethods = false) + static class DoubleRegistrationUndertowDeploymentInfoCustomizerConfiguration { + + private final UndertowDeploymentInfoCustomizer customizer = mock(UndertowDeploymentInfoCustomizer.class); + + @Bean + UndertowDeploymentInfoCustomizer deploymentInfoCustomizer() { + return this.customizer; + } + + @Bean + WebServerFactoryCustomizer undertowCustomizer() { + return (undertow) -> undertow.addDeploymentInfoCustomizers(this.customizer); + } + + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/UndertowServletWebServerFactoryCustomizerTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/servlet/undertow/UndertowServletWebServerFactoryCustomizerTests.java similarity index 88% rename from spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/UndertowServletWebServerFactoryCustomizerTests.java rename to spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/servlet/undertow/UndertowServletWebServerFactoryCustomizerTests.java index 00588675a0..c68a6dd0e2 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/UndertowServletWebServerFactoryCustomizerTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/servlet/undertow/UndertowServletWebServerFactoryCustomizerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,12 +14,12 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.web.servlet; +package org.springframework.boot.autoconfigure.web.server.servlet.undertow; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.web.ServerProperties; -import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory; +import org.springframework.boot.web.server.servlet.undertow.UndertowServletWebServerFactory; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/TomcatVirtualThreadsWebServerFactoryCustomizerTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/tomcat/TomcatVirtualThreadsWebServerFactoryCustomizerTests.java similarity index 87% rename from spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/TomcatVirtualThreadsWebServerFactoryCustomizerTests.java rename to spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/tomcat/TomcatVirtualThreadsWebServerFactoryCustomizerTests.java index 5fcf72d1f9..0a4962b104 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/TomcatVirtualThreadsWebServerFactoryCustomizerTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/tomcat/TomcatVirtualThreadsWebServerFactoryCustomizerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.web.embedded; +package org.springframework.boot.autoconfigure.web.server.tomcat; import java.util.function.Consumer; @@ -23,8 +23,8 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledForJreRange; import org.junit.jupiter.api.condition.JRE; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; -import org.springframework.boot.web.embedded.tomcat.TomcatWebServer; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.tomcat.TomcatWebServer; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizerTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/tomcat/TomcatWebServerFactoryCustomizerTests.java similarity index 99% rename from spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizerTests.java rename to spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/tomcat/TomcatWebServerFactoryCustomizerTests.java index cc34e5359c..8297ab3ba0 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizerTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/tomcat/TomcatWebServerFactoryCustomizerTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.web.embedded; +package org.springframework.boot.autoconfigure.web.server.tomcat; import java.util.Locale; import java.util.function.Consumer; @@ -37,9 +37,9 @@ import org.springframework.boot.autoconfigure.web.ServerProperties.ForwardHeader import org.springframework.boot.context.properties.bind.Bindable; import org.springframework.boot.context.properties.bind.Binder; import org.springframework.boot.context.properties.source.ConfigurationPropertySources; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; -import org.springframework.boot.web.embedded.tomcat.TomcatWebServer; import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.tomcat.TomcatWebServer; import org.springframework.mock.env.MockEnvironment; import org.springframework.test.context.support.TestPropertySourceUtils; import org.springframework.util.unit.DataSize; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/UndertowWebServerFactoryCustomizerTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/undertow/UndertowWebServerFactoryCustomizerTests.java similarity index 97% rename from spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/UndertowWebServerFactoryCustomizerTests.java rename to spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/undertow/UndertowWebServerFactoryCustomizerTests.java index e5a2c95e82..74896ff2a1 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/UndertowWebServerFactoryCustomizerTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/server/undertow/UndertowWebServerFactoryCustomizerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.web.embedded; +package org.springframework.boot.autoconfigure.web.server.undertow; import java.io.File; import java.nio.charset.StandardCharsets; @@ -33,8 +33,8 @@ import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.context.properties.bind.Bindable; import org.springframework.boot.context.properties.bind.Binder; import org.springframework.boot.context.properties.source.ConfigurationPropertySources; -import org.springframework.boot.web.embedded.undertow.ConfigurableUndertowWebServerFactory; -import org.springframework.boot.web.embedded.undertow.UndertowBuilderCustomizer; +import org.springframework.boot.web.server.undertow.ConfigurableUndertowWebServerFactory; +import org.springframework.boot.web.server.undertow.UndertowBuilderCustomizer; import org.springframework.mock.env.MockEnvironment; import org.springframework.test.context.support.TestPropertySourceUtils; import org.springframework.test.util.ReflectionTestUtils; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/FilterOrderingIntegrationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/FilterOrderingIntegrationTests.java index af2267b28d..776fc597ff 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/FilterOrderingIntegrationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/FilterOrderingIntegrationTests.java @@ -29,11 +29,11 @@ import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfi import org.springframework.boot.autoconfigure.session.SessionAutoConfiguration; import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor; +import org.springframework.boot.web.server.servlet.MockServletWebServer.RegisteredFilter; +import org.springframework.boot.web.server.servlet.MockServletWebServerFactory; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter; import org.springframework.boot.web.servlet.filter.OrderedRequestContextFilter; -import org.springframework.boot.web.servlet.server.MockServletWebServer.RegisteredFilter; -import org.springframework.boot.web.servlet.server.MockServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnection; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/HttpEncodingAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/HttpEncodingAutoConfigurationTests.java index 1fbcdd9b36..0f3d758322 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/HttpEncodingAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/HttpEncodingAutoConfigurationTests.java @@ -26,10 +26,10 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor; +import org.springframework.boot.web.server.servlet.MockServletWebServerFactory; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebApplicationContext; import org.springframework.boot.web.servlet.filter.OrderedFormContentFilter; import org.springframework.boot.web.servlet.filter.OrderedHiddenHttpMethodFilter; -import org.springframework.boot.web.servlet.server.MockServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.AnnotationAwareOrderComparator; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/MultipartAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/MultipartAutoConfigurationTests.java index edbc441d87..7ed0884992 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/MultipartAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/MultipartAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,13 +27,14 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.boot.testsupport.classpath.ForkedClassPath; import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories; -import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; -import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory; +import org.springframework.boot.web.server.servlet.jetty.JettyServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.servlet.undertow.UndertowServletWebServerFactory; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -263,7 +264,7 @@ class MultipartAutoConfigurationTests { } @Configuration(proxyBeanMethods = false) - @Import({ ServletWebServerFactoryAutoConfiguration.class, DispatcherServletAutoConfiguration.class, + @Import({ TomcatServletWebServerAutoConfiguration.class, DispatcherServletAutoConfiguration.class, MultipartAutoConfiguration.class }) @EnableConfigurationProperties(MultipartProperties.class) static class BaseConfiguration { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryAutoConfigurationTests.java deleted file mode 100644 index 9bad1433a1..0000000000 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryAutoConfigurationTests.java +++ /dev/null @@ -1,601 +0,0 @@ -/* - * Copyright 2012-2025 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.autoconfigure.web.servlet; - -import io.undertow.Undertow.Builder; -import io.undertow.servlet.api.DeploymentInfo; -import jakarta.servlet.Filter; -import jakarta.servlet.ServletContext; -import org.apache.catalina.Context; -import org.apache.catalina.connector.Connector; -import org.apache.catalina.startup.Tomcat; -import org.eclipse.jetty.server.Server; -import org.junit.jupiter.api.Test; -import reactor.netty.http.server.HttpServer; - -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.boot.test.context.FilteredClassLoader; -import org.springframework.boot.test.context.runner.WebApplicationContextRunner; -import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer; -import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory; -import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer; -import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer; -import org.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; -import org.springframework.boot.web.embedded.undertow.UndertowBuilderCustomizer; -import org.springframework.boot.web.embedded.undertow.UndertowDeploymentInfoCustomizer; -import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory; -import org.springframework.boot.web.server.WebServerFactoryCustomizer; -import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; -import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactory; -import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; -import org.springframework.boot.web.servlet.server.CookieSameSiteSupplier; -import org.springframework.boot.web.servlet.server.MockServletWebServerFactory; -import org.springframework.boot.web.servlet.server.ServletWebServerFactory; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.stereotype.Component; -import org.springframework.web.filter.ForwardedHeaderFilter; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.mock; - -/** - * Tests for {@link ServletWebServerFactoryAutoConfiguration}. - * - * @author Dave Syer - * @author Phillip Webb - * @author Stephane Nicoll - * @author Raheela Aslam - * @author Madhura Bhave - */ -class ServletWebServerFactoryAutoConfigurationTests { - - private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner( - AnnotationConfigServletWebServerApplicationContext::new) - .withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class)) - .withUserConfiguration(WebServerConfiguration.class); - - @Test - void createFromConfigClass() { - this.contextRunner.run((context) -> assertThat(context).hasSingleBean(ServletWebServerFactoryCustomizer.class)); - } - - @Test - void webServerHasNoServletContext() { - this.contextRunner.withUserConfiguration(EnsureWebServerHasNoServletContext.class) - .run((context) -> assertThat(context).hasNotFailed()); - } - - @Test - void webServerFactoryCustomizerBeansAreCalledToCustomizeWebServerFactory() { - this.contextRunner - .withBean(WebServerFactoryCustomizer.class, - () -> (WebServerFactoryCustomizer) (factory) -> factory - .setPort(9000)) - .run((context) -> assertThat(context.getBean(MockServletWebServerFactory.class).getPort()).isEqualTo(9000)); - } - - @Test - void initParametersAreConfiguredOnTheServletContext() { - this.contextRunner - .withPropertyValues("server.servlet.context-parameters.a:alpha", - "server.servlet.context-parameters.b:bravo") - .run((context) -> { - ServletContext servletContext = context.getServletContext(); - assertThat(servletContext.getInitParameter("a")).isEqualTo("alpha"); - assertThat(servletContext.getInitParameter("b")).isEqualTo("bravo"); - }); - } - - @Test - void jettyServerCustomizerBeanIsAddedToFactory() { - WebApplicationContextRunner runner = new WebApplicationContextRunner( - AnnotationConfigServletWebServerApplicationContext::new) - .withClassLoader(new FilteredClassLoader(Tomcat.class, HttpServer.class)) - .withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class)) - .withUserConfiguration(JettyServerCustomizerConfiguration.class) - .withPropertyValues("server.port:0"); - runner.run((context) -> { - JettyServletWebServerFactory factory = context.getBean(JettyServletWebServerFactory.class); - assertThat(factory.getServerCustomizers()).hasSize(1); - }); - } - - @Test - void jettyServerCustomizerRegisteredAsBeanAndViaFactoryIsOnlyCalledOnce() { - WebApplicationContextRunner runner = new WebApplicationContextRunner( - AnnotationConfigServletWebServerApplicationContext::new) - .withClassLoader(new FilteredClassLoader(Tomcat.class, HttpServer.class)) - .withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class)) - .withUserConfiguration(DoubleRegistrationJettyServerCustomizerConfiguration.class) - .withPropertyValues("server.port: 0"); - runner.run((context) -> { - JettyServletWebServerFactory factory = context.getBean(JettyServletWebServerFactory.class); - JettyServerCustomizer customizer = context.getBean("serverCustomizer", JettyServerCustomizer.class); - assertThat(factory.getServerCustomizers()).contains(customizer); - then(customizer).should().customize(any(Server.class)); - }); - } - - @Test - void undertowDeploymentInfoCustomizerBeanIsAddedToFactory() { - WebApplicationContextRunner runner = new WebApplicationContextRunner( - AnnotationConfigServletWebServerApplicationContext::new) - .withClassLoader(new FilteredClassLoader(Tomcat.class, HttpServer.class, Server.class)) - .withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class)) - .withUserConfiguration(UndertowDeploymentInfoCustomizerConfiguration.class) - .withPropertyValues("server.port:0"); - runner.run((context) -> { - UndertowServletWebServerFactory factory = context.getBean(UndertowServletWebServerFactory.class); - assertThat(factory.getDeploymentInfoCustomizers()).hasSize(1); - }); - } - - @Test - void undertowDeploymentInfoCustomizerRegisteredAsBeanAndViaFactoryIsOnlyCalledOnce() { - WebApplicationContextRunner runner = new WebApplicationContextRunner( - AnnotationConfigServletWebServerApplicationContext::new) - .withClassLoader(new FilteredClassLoader(Tomcat.class, HttpServer.class, Server.class)) - .withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class)) - .withUserConfiguration(DoubleRegistrationUndertowDeploymentInfoCustomizerConfiguration.class) - .withPropertyValues("server.port: 0"); - runner.run((context) -> { - UndertowServletWebServerFactory factory = context.getBean(UndertowServletWebServerFactory.class); - UndertowDeploymentInfoCustomizer customizer = context.getBean("deploymentInfoCustomizer", - UndertowDeploymentInfoCustomizer.class); - assertThat(factory.getDeploymentInfoCustomizers()).contains(customizer); - then(customizer).should().customize(any(DeploymentInfo.class)); - }); - } - - @Test - void undertowBuilderCustomizerRegisteredAsBeanAndViaFactoryIsOnlyCalledOnce() { - WebApplicationContextRunner runner = new WebApplicationContextRunner( - AnnotationConfigServletWebServerApplicationContext::new) - .withClassLoader(new FilteredClassLoader(Tomcat.class, HttpServer.class, Server.class)) - .withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class)) - .withUserConfiguration(DoubleRegistrationUndertowBuilderCustomizerConfiguration.class) - .withPropertyValues("server.port: 0"); - runner.run((context) -> { - UndertowServletWebServerFactory factory = context.getBean(UndertowServletWebServerFactory.class); - UndertowBuilderCustomizer customizer = context.getBean("builderCustomizer", - UndertowBuilderCustomizer.class); - assertThat(factory.getBuilderCustomizers()).contains(customizer); - then(customizer).should().customize(any(Builder.class)); - }); - } - - @Test - void undertowBuilderCustomizerBeanIsAddedToFactory() { - WebApplicationContextRunner runner = new WebApplicationContextRunner( - AnnotationConfigServletWebServerApplicationContext::new) - .withClassLoader(new FilteredClassLoader(Tomcat.class, HttpServer.class, Server.class)) - .withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class)) - .withUserConfiguration(UndertowBuilderCustomizerConfiguration.class) - .withPropertyValues("server.port:0"); - runner.run((context) -> { - UndertowServletWebServerFactory factory = context.getBean(UndertowServletWebServerFactory.class); - assertThat(factory.getBuilderCustomizers()).hasSize(1); - }); - } - - @Test - void undertowServletWebServerFactoryCustomizerIsAutoConfigured() { - WebApplicationContextRunner runner = new WebApplicationContextRunner( - AnnotationConfigServletWebServerApplicationContext::new) - .withClassLoader(new FilteredClassLoader(Tomcat.class, HttpServer.class, Server.class)) - .withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class)) - .withUserConfiguration(UndertowBuilderCustomizerConfiguration.class) - .withPropertyValues("server.port:0"); - runner.run((context) -> assertThat(context).hasSingleBean(UndertowServletWebServerFactoryCustomizer.class)); - } - - @Test - void tomcatConnectorCustomizerBeanIsAddedToFactory() { - WebApplicationContextRunner runner = new WebApplicationContextRunner( - AnnotationConfigServletWebServerApplicationContext::new) - .withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class)) - .withUserConfiguration(TomcatConnectorCustomizerConfiguration.class) - .withPropertyValues("server.port: 0"); - runner.run((context) -> { - TomcatServletWebServerFactory factory = context.getBean(TomcatServletWebServerFactory.class); - TomcatConnectorCustomizer customizer = context.getBean("connectorCustomizer", - TomcatConnectorCustomizer.class); - assertThat(factory.getTomcatConnectorCustomizers()).contains(customizer); - then(customizer).should().customize(any(Connector.class)); - }); - } - - @Test - void tomcatConnectorCustomizerRegisteredAsBeanAndViaFactoryIsOnlyCalledOnce() { - WebApplicationContextRunner runner = new WebApplicationContextRunner( - AnnotationConfigServletWebServerApplicationContext::new) - .withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class)) - .withUserConfiguration(DoubleRegistrationTomcatConnectorCustomizerConfiguration.class) - .withPropertyValues("server.port: 0"); - runner.run((context) -> { - TomcatServletWebServerFactory factory = context.getBean(TomcatServletWebServerFactory.class); - TomcatConnectorCustomizer customizer = context.getBean("connectorCustomizer", - TomcatConnectorCustomizer.class); - assertThat(factory.getTomcatConnectorCustomizers()).contains(customizer); - then(customizer).should().customize(any(Connector.class)); - }); - } - - @Test - void tomcatContextCustomizerBeanIsAddedToFactory() { - WebApplicationContextRunner runner = new WebApplicationContextRunner( - AnnotationConfigServletWebServerApplicationContext::new) - .withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class)) - .withUserConfiguration(TomcatContextCustomizerConfiguration.class) - .withPropertyValues("server.port: 0"); - runner.run((context) -> { - TomcatServletWebServerFactory factory = context.getBean(TomcatServletWebServerFactory.class); - TomcatContextCustomizer customizer = context.getBean("contextCustomizer", TomcatContextCustomizer.class); - assertThat(factory.getTomcatContextCustomizers()).contains(customizer); - then(customizer).should().customize(any(Context.class)); - }); - } - - @Test - void tomcatContextCustomizerRegisteredAsBeanAndViaFactoryIsOnlyCalledOnce() { - WebApplicationContextRunner runner = new WebApplicationContextRunner( - AnnotationConfigServletWebServerApplicationContext::new) - .withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class)) - .withUserConfiguration(DoubleRegistrationTomcatContextCustomizerConfiguration.class) - .withPropertyValues("server.port: 0"); - runner.run((context) -> { - TomcatServletWebServerFactory factory = context.getBean(TomcatServletWebServerFactory.class); - TomcatContextCustomizer customizer = context.getBean("contextCustomizer", TomcatContextCustomizer.class); - assertThat(factory.getTomcatContextCustomizers()).contains(customizer); - then(customizer).should().customize(any(Context.class)); - }); - } - - @Test - void tomcatProtocolHandlerCustomizerBeanIsAddedToFactory() { - WebApplicationContextRunner runner = new WebApplicationContextRunner( - AnnotationConfigServletWebServerApplicationContext::new) - .withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class)) - .withUserConfiguration(TomcatProtocolHandlerCustomizerConfiguration.class) - .withPropertyValues("server.port: 0"); - runner.run((context) -> { - TomcatServletWebServerFactory factory = context.getBean(TomcatServletWebServerFactory.class); - TomcatProtocolHandlerCustomizer customizer = context.getBean("protocolHandlerCustomizer", - TomcatProtocolHandlerCustomizer.class); - assertThat(factory.getTomcatProtocolHandlerCustomizers()).contains(customizer); - then(customizer).should().customize(any()); - }); - } - - @Test - void tomcatProtocolHandlerCustomizerRegisteredAsBeanAndViaFactoryIsOnlyCalledOnce() { - WebApplicationContextRunner runner = new WebApplicationContextRunner( - AnnotationConfigServletWebServerApplicationContext::new) - .withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class)) - .withUserConfiguration(DoubleRegistrationTomcatProtocolHandlerCustomizerConfiguration.class) - .withPropertyValues("server.port: 0"); - runner.run((context) -> { - TomcatServletWebServerFactory factory = context.getBean(TomcatServletWebServerFactory.class); - TomcatProtocolHandlerCustomizer customizer = context.getBean("protocolHandlerCustomizer", - TomcatProtocolHandlerCustomizer.class); - assertThat(factory.getTomcatProtocolHandlerCustomizers()).contains(customizer); - then(customizer).should().customize(any()); - }); - } - - @Test - void forwardedHeaderFilterShouldBeConfigured() { - this.contextRunner.withPropertyValues("server.forward-headers-strategy=framework").run((context) -> { - assertThat(context).hasSingleBean(FilterRegistrationBean.class); - Filter filter = context.getBean(FilterRegistrationBean.class).getFilter(); - assertThat(filter).isInstanceOf(ForwardedHeaderFilter.class); - assertThat(filter).extracting("relativeRedirects").isEqualTo(false); - }); - } - - @Test - void forwardedHeaderFilterWhenStrategyNotFilterShouldNotBeConfigured() { - this.contextRunner.withPropertyValues("server.forward-headers-strategy=native") - .run((context) -> assertThat(context).doesNotHaveBean(FilterRegistrationBean.class)); - } - - @Test - void forwardedHeaderFilterWhenFilterAlreadyRegisteredShouldBackOff() { - this.contextRunner.withUserConfiguration(ForwardedHeaderFilterConfiguration.class) - .withPropertyValues("server.forward-headers-strategy=framework") - .run((context) -> assertThat(context).hasSingleBean(FilterRegistrationBean.class)); - } - - @Test - void cookieSameSiteSuppliersAreApplied() { - this.contextRunner.withUserConfiguration(CookieSameSiteSupplierConfiguration.class).run((context) -> { - AbstractServletWebServerFactory webServerFactory = context.getBean(AbstractServletWebServerFactory.class); - assertThat(webServerFactory.getCookieSameSiteSuppliers()).hasSize(2); - }); - } - - @Test - void relativeRedirectsShouldBeEnabledWhenUsingTomcatContainerAndUseRelativeRedirects() { - WebApplicationContextRunner runner = new WebApplicationContextRunner( - AnnotationConfigServletWebServerApplicationContext::new) - .withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class)) - .withPropertyValues("server.forward-headers-strategy=framework", - "server.tomcat.use-relative-redirects=true", "server.port=0"); - runner.run((context) -> { - Filter filter = context.getBean(FilterRegistrationBean.class).getFilter(); - assertThat(filter).isInstanceOf(ForwardedHeaderFilter.class); - assertThat(filter).extracting("relativeRedirects").isEqualTo(true); - }); - } - - @Test - void relativeRedirectsShouldNotBeEnabledWhenUsingTomcatContainerAndNotUsingRelativeRedirects() { - WebApplicationContextRunner runner = new WebApplicationContextRunner( - AnnotationConfigServletWebServerApplicationContext::new) - .withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class)) - .withPropertyValues("server.forward-headers-strategy=framework", - "server.tomcat.use-relative-redirects=false", "server.port=0"); - runner.run((context) -> { - Filter filter = context.getBean(FilterRegistrationBean.class).getFilter(); - assertThat(filter).isInstanceOf(ForwardedHeaderFilter.class); - assertThat(filter).extracting("relativeRedirects").isEqualTo(false); - }); - } - - @Test - void relativeRedirectsShouldNotBeEnabledWhenNotUsingTomcatContainer() { - WebApplicationContextRunner runner = new WebApplicationContextRunner( - AnnotationConfigServletWebServerApplicationContext::new) - .withClassLoader(new FilteredClassLoader(Tomcat.class, Server.class)) - .withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class)) - .withPropertyValues("server.forward-headers-strategy=framework", "server.port=0"); - runner.run((context) -> { - Filter filter = context.getBean(FilterRegistrationBean.class).getFilter(); - assertThat(filter).isInstanceOf(ForwardedHeaderFilter.class); - assertThat(filter).extracting("relativeRedirects").isEqualTo(false); - }); - } - - @Configuration(proxyBeanMethods = false) - @ConditionalOnExpression("true") - static class WebServerConfiguration { - - @Bean - ServletWebServerFactory webServerFactory() { - return new MockServletWebServerFactory(); - } - - } - - @Component - static class EnsureWebServerHasNoServletContext implements BeanPostProcessor { - - @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) { - if (bean instanceof ConfigurableServletWebServerFactory) { - MockServletWebServerFactory webServerFactory = (MockServletWebServerFactory) bean; - assertThat(webServerFactory.getServletContext()).isNull(); - } - return bean; - } - - @Override - public Object postProcessAfterInitialization(Object bean, String beanName) { - return bean; - } - - } - - @Configuration(proxyBeanMethods = false) - static class TomcatConnectorCustomizerConfiguration { - - @Bean - TomcatConnectorCustomizer connectorCustomizer() { - return mock(TomcatConnectorCustomizer.class); - } - - } - - @Configuration(proxyBeanMethods = false) - static class DoubleRegistrationTomcatConnectorCustomizerConfiguration { - - private final TomcatConnectorCustomizer customizer = mock(TomcatConnectorCustomizer.class); - - @Bean - TomcatConnectorCustomizer connectorCustomizer() { - return this.customizer; - } - - @Bean - WebServerFactoryCustomizer tomcatCustomizer() { - return (tomcat) -> tomcat.addConnectorCustomizers(this.customizer); - } - - } - - @Configuration(proxyBeanMethods = false) - static class TomcatContextCustomizerConfiguration { - - @Bean - TomcatContextCustomizer contextCustomizer() { - return mock(TomcatContextCustomizer.class); - } - - } - - @Configuration(proxyBeanMethods = false) - static class DoubleRegistrationTomcatContextCustomizerConfiguration { - - private final TomcatContextCustomizer customizer = mock(TomcatContextCustomizer.class); - - @Bean - TomcatContextCustomizer contextCustomizer() { - return this.customizer; - } - - @Bean - WebServerFactoryCustomizer tomcatCustomizer() { - return (tomcat) -> tomcat.addContextCustomizers(this.customizer); - } - - } - - @Configuration(proxyBeanMethods = false) - static class TomcatProtocolHandlerCustomizerConfiguration { - - @Bean - TomcatProtocolHandlerCustomizer protocolHandlerCustomizer() { - return mock(TomcatProtocolHandlerCustomizer.class); - } - - } - - @Configuration(proxyBeanMethods = false) - static class DoubleRegistrationTomcatProtocolHandlerCustomizerConfiguration { - - private final TomcatProtocolHandlerCustomizer customizer = mock(TomcatProtocolHandlerCustomizer.class); - - @Bean - TomcatProtocolHandlerCustomizer protocolHandlerCustomizer() { - return this.customizer; - } - - @Bean - WebServerFactoryCustomizer tomcatCustomizer() { - return (tomcat) -> tomcat.addProtocolHandlerCustomizers(this.customizer); - } - - } - - @Configuration(proxyBeanMethods = false) - static class JettyServerCustomizerConfiguration { - - @Bean - JettyServerCustomizer serverCustomizer() { - return (server) -> { - }; - } - - } - - @Configuration(proxyBeanMethods = false) - static class DoubleRegistrationJettyServerCustomizerConfiguration { - - private final JettyServerCustomizer customizer = mock(JettyServerCustomizer.class); - - @Bean - JettyServerCustomizer serverCustomizer() { - return this.customizer; - } - - @Bean - WebServerFactoryCustomizer jettyCustomizer() { - return (jetty) -> jetty.addServerCustomizers(this.customizer); - } - - } - - @Configuration(proxyBeanMethods = false) - static class UndertowBuilderCustomizerConfiguration { - - @Bean - UndertowBuilderCustomizer builderCustomizer() { - return (builder) -> { - }; - } - - } - - @Configuration(proxyBeanMethods = false) - static class DoubleRegistrationUndertowBuilderCustomizerConfiguration { - - private final UndertowBuilderCustomizer customizer = mock(UndertowBuilderCustomizer.class); - - @Bean - UndertowBuilderCustomizer builderCustomizer() { - return this.customizer; - } - - @Bean - WebServerFactoryCustomizer undertowCustomizer() { - return (undertow) -> undertow.addBuilderCustomizers(this.customizer); - } - - } - - @Configuration(proxyBeanMethods = false) - static class UndertowDeploymentInfoCustomizerConfiguration { - - @Bean - UndertowDeploymentInfoCustomizer deploymentInfoCustomizer() { - return (deploymentInfo) -> { - }; - } - - } - - @Configuration(proxyBeanMethods = false) - static class DoubleRegistrationUndertowDeploymentInfoCustomizerConfiguration { - - private final UndertowDeploymentInfoCustomizer customizer = mock(UndertowDeploymentInfoCustomizer.class); - - @Bean - UndertowDeploymentInfoCustomizer deploymentInfoCustomizer() { - return this.customizer; - } - - @Bean - WebServerFactoryCustomizer undertowCustomizer() { - return (undertow) -> undertow.addDeploymentInfoCustomizers(this.customizer); - } - - } - - @Configuration(proxyBeanMethods = false) - static class ForwardedHeaderFilterConfiguration { - - @Bean - FilterRegistrationBean testForwardedHeaderFilter() { - ForwardedHeaderFilter filter = new ForwardedHeaderFilter(); - return new FilterRegistrationBean<>(filter); - } - - } - - @Configuration(proxyBeanMethods = false) - static class CookieSameSiteSupplierConfiguration { - - @Bean - CookieSameSiteSupplier cookieSameSiteSupplier1() { - return CookieSameSiteSupplier.ofLax().whenHasName("test1"); - } - - @Bean - CookieSameSiteSupplier cookieSameSiteSupplier2() { - return CookieSameSiteSupplier.ofNone().whenHasName("test2"); - } - - } - -} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java index 44e0c9d318..70a7465708 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java @@ -58,14 +58,14 @@ import org.springframework.boot.test.context.assertj.AssertableWebApplicationCon import org.springframework.boot.test.context.runner.ContextConsumer; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.boot.testsupport.classpath.resources.WithResource; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor; +import org.springframework.boot.web.server.servlet.MockServletWebServerFactory; +import org.springframework.boot.web.server.servlet.ServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.boot.web.servlet.filter.OrderedFormContentFilter; -import org.springframework.boot.web.servlet.server.MockServletWebServerFactory; -import org.springframework.boot.web.servlet.server.ServletWebServerFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WelcomePageIntegrationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WelcomePageIntegrationTests.java index a34b15f8be..f1c289e5da 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WelcomePageIntegrationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WelcomePageIntegrationTests.java @@ -23,6 +23,7 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration; import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; @@ -73,7 +74,7 @@ class WelcomePageIntegrationTests { @Configuration @Import({ PropertyPlaceholderAutoConfiguration.class, WebMvcAutoConfiguration.class, - HttpMessageConvertersAutoConfiguration.class, ServletWebServerFactoryAutoConfiguration.class, + HttpMessageConvertersAutoConfiguration.class, TomcatServletWebServerAutoConfiguration.class, DispatcherServletAutoConfiguration.class, ThymeleafAutoConfiguration.class }) static class TestConfiguration { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/BasicErrorControllerDirectMockMvcTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/BasicErrorControllerDirectMockMvcTests.java index b09718bbea..0627725141 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/BasicErrorControllerDirectMockMvcTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/BasicErrorControllerDirectMockMvcTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,8 +33,8 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.test.util.ApplicationContextTestUtils; @@ -111,7 +111,7 @@ class BasicErrorControllerDirectMockMvcTests { @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented - @Import({ ServletWebServerFactoryAutoConfiguration.class, DispatcherServletAutoConfiguration.class, + @Import({ TomcatServletWebServerAutoConfiguration.class, DispatcherServletAutoConfiguration.class, WebMvcAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, ErrorMvcAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class }) protected @interface MinimalWebConfiguration { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/BasicErrorControllerIntegrationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/BasicErrorControllerIntegrationTests.java index 5baf1f67c3..40e9c13a8c 100755 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/BasicErrorControllerIntegrationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/BasicErrorControllerIntegrationTests.java @@ -42,8 +42,8 @@ import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoCon import org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration; import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration; import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.boot.testsupport.classpath.resources.WithResource; @@ -397,7 +397,7 @@ class BasicErrorControllerIntegrationTests { @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented - @ImportAutoConfiguration({ ServletWebServerFactoryAutoConfiguration.class, DispatcherServletAutoConfiguration.class, + @ImportAutoConfiguration({ TomcatServletWebServerAutoConfiguration.class, DispatcherServletAutoConfiguration.class, WebMvcAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, ErrorMvcAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class }) private @interface MinimalWebConfiguration { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/BasicErrorControllerMockMvcTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/BasicErrorControllerMockMvcTests.java index beda7a4a53..e429f5676c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/BasicErrorControllerMockMvcTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/BasicErrorControllerMockMvcTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,7 +37,6 @@ import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Bean; @@ -128,9 +127,9 @@ class BasicErrorControllerMockMvcTests { @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented - @ImportAutoConfiguration({ ServletWebServerFactoryAutoConfiguration.class, DispatcherServletAutoConfiguration.class, - WebMvcAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, - ErrorMvcAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class }) + @ImportAutoConfiguration({ DispatcherServletAutoConfiguration.class, WebMvcAutoConfiguration.class, + HttpMessageConvertersAutoConfiguration.class, ErrorMvcAutoConfiguration.class, + PropertyPlaceholderAutoConfiguration.class }) private @interface MinimalWebConfiguration { } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/DefaultErrorViewIntegrationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/DefaultErrorViewIntegrationTests.java index 10212b89b3..43454a9358 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/DefaultErrorViewIntegrationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/DefaultErrorViewIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,6 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Configuration; @@ -96,9 +95,9 @@ class DefaultErrorViewIntegrationTests { @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented - @Import({ ServletWebServerFactoryAutoConfiguration.class, DispatcherServletAutoConfiguration.class, - WebMvcAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, - ErrorMvcAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class }) + @Import({ DispatcherServletAutoConfiguration.class, WebMvcAutoConfiguration.class, + HttpMessageConvertersAutoConfiguration.class, ErrorMvcAutoConfiguration.class, + PropertyPlaceholderAutoConfiguration.class }) protected @interface MinimalWebConfiguration { } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/RemappedErrorViewIntegrationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/RemappedErrorViewIntegrationTests.java index 2baaf793f2..8e6887980e 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/RemappedErrorViewIntegrationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/RemappedErrorViewIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,8 +20,8 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.test.context.SpringBootTest; @@ -69,7 +69,7 @@ class RemappedErrorViewIntegrationTests { @Configuration(proxyBeanMethods = false) @Import({ PropertyPlaceholderAutoConfiguration.class, WebMvcAutoConfiguration.class, - HttpMessageConvertersAutoConfiguration.class, ServletWebServerFactoryAutoConfiguration.class, + HttpMessageConvertersAutoConfiguration.class, TomcatServletWebServerAutoConfiguration.class, DispatcherServletAutoConfiguration.class, ErrorMvcAutoConfiguration.class }) @Controller static class TestConfiguration implements ErrorPageRegistrar { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/websocket/reactive/WebSocketReactiveAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/websocket/reactive/WebSocketReactiveAutoConfigurationTests.java deleted file mode 100644 index e092a9262f..0000000000 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/websocket/reactive/WebSocketReactiveAutoConfigurationTests.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2012-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.autoconfigure.websocket.reactive; - -import java.util.function.Function; -import java.util.stream.Stream; - -import jakarta.servlet.ServletContext; -import jakarta.websocket.server.ServerContainer; -import org.apache.catalina.Container; -import org.apache.catalina.Context; -import org.apache.catalina.startup.Tomcat; -import org.eclipse.jetty.ee10.servlet.ServletContextHandler; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import org.springframework.boot.testsupport.classpath.ForkedClassPath; -import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories; -import org.springframework.boot.web.embedded.jetty.JettyReactiveWebServerFactory; -import org.springframework.boot.web.embedded.jetty.JettyWebServer; -import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory; -import org.springframework.boot.web.embedded.tomcat.TomcatWebServer; -import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext; -import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; -import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.server.reactive.HttpHandler; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link WebSocketReactiveAutoConfiguration}. - * - * @author Andy Wilkinson - */ -@DirtiesUrlFactories -class WebSocketReactiveAutoConfigurationTests { - - @ParameterizedTest(name = "{0}") - @MethodSource("testConfiguration") - @ForkedClassPath - void serverContainerIsAvailableFromTheServletContext(String server, - Function servletContextAccessor, - Class... configuration) { - try (AnnotationConfigReactiveWebServerApplicationContext context = new AnnotationConfigReactiveWebServerApplicationContext( - configuration)) { - Object serverContainer = servletContextAccessor.apply(context) - .getAttribute("jakarta.websocket.server.ServerContainer"); - assertThat(serverContainer).isInstanceOf(ServerContainer.class); - } - } - - static Stream testConfiguration() { - return Stream.of(Arguments.of("Jetty", - (Function) WebSocketReactiveAutoConfigurationTests::getJettyServletContext, - new Class[] { JettyConfiguration.class, - WebSocketReactiveAutoConfiguration.JettyWebSocketConfiguration.class }), - Arguments.of("Tomcat", - (Function) WebSocketReactiveAutoConfigurationTests::getTomcatServletContext, - new Class[] { TomcatConfiguration.class, - WebSocketReactiveAutoConfiguration.TomcatWebSocketConfiguration.class })); - } - - private static ServletContext getJettyServletContext(AnnotationConfigReactiveWebServerApplicationContext context) { - return ((ServletContextHandler) ((JettyWebServer) context.getWebServer()).getServer().getHandler()) - .getServletContext(); - } - - private static ServletContext getTomcatServletContext(AnnotationConfigReactiveWebServerApplicationContext context) { - return findContext(((TomcatWebServer) context.getWebServer()).getTomcat()).getServletContext(); - } - - private static Context findContext(Tomcat tomcat) { - for (Container child : tomcat.getHost().findChildren()) { - if (child instanceof Context context) { - return context; - } - } - throw new IllegalStateException("The host does not contain a Context"); - } - - @Configuration(proxyBeanMethods = false) - static class CommonConfiguration { - - @Bean - static WebServerFactoryCustomizerBeanPostProcessor webServerFactoryCustomizerBeanPostProcessor() { - return new WebServerFactoryCustomizerBeanPostProcessor(); - } - - @Bean - HttpHandler echoHandler() { - return (request, response) -> response.writeWith(request.getBody()); - } - - } - - @Configuration(proxyBeanMethods = false) - static class TomcatConfiguration extends CommonConfiguration { - - @Bean - ReactiveWebServerFactory webServerFactory() { - TomcatReactiveWebServerFactory factory = new TomcatReactiveWebServerFactory(); - factory.setPort(0); - return factory; - } - - } - - @Configuration(proxyBeanMethods = false) - static class JettyConfiguration extends CommonConfiguration { - - @Bean - ReactiveWebServerFactory webServerFactory() { - JettyReactiveWebServerFactory factory = new JettyReactiveWebServerFactory(); - factory.setPort(0); - return factory; - } - - } - -} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/websocket/servlet/WebSocketMessagingAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/websocket/servlet/WebSocketMessagingAutoConfigurationTests.java index 323d99e3a1..b1c607e1c3 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/websocket/servlet/WebSocketMessagingAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/websocket/servlet/WebSocketMessagingAutoConfigurationTests.java @@ -39,12 +39,13 @@ import org.springframework.boot.LazyInitializationBeanFactoryPostProcessor; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; import org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.tomcat.WebSocketTomcatWebServerFactoryCustomizer; import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; import org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration.WebSocketMessageConverterConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.test.util.TestPropertyValues; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -261,7 +262,7 @@ class WebSocketMessagingAutoConfigurationTests { @EnableWebSocket @EnableConfigurationProperties @EnableWebSocketMessageBroker - @ImportAutoConfiguration({ JacksonAutoConfiguration.class, ServletWebServerFactoryAutoConfiguration.class, + @ImportAutoConfiguration({ JacksonAutoConfiguration.class, TomcatServletWebServerAutoConfiguration.class, WebSocketMessagingAutoConfiguration.class, DispatcherServletAutoConfiguration.class }) static class WebSocketMessagingConfiguration implements WebSocketMessageBrokerConfigurer { @@ -287,8 +288,8 @@ class WebSocketMessagingAutoConfigurationTests { } @Bean - TomcatWebSocketServletWebServerCustomizer tomcatCustomizer() { - return new TomcatWebSocketServletWebServerCustomizer(); + WebSocketTomcatWebServerFactoryCustomizer tomcatCustomizer() { + return new WebSocketTomcatWebServerFactoryCustomizer(); } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/websocket/servlet/WebSocketServletAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/websocket/servlet/WebSocketServletAutoConfigurationTests.java deleted file mode 100644 index 9d6ef0b784..0000000000 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/websocket/servlet/WebSocketServletAutoConfigurationTests.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright 2012-2025 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.autoconfigure.websocket.servlet; - -import java.io.IOException; -import java.util.Map; -import java.util.stream.Stream; - -import jakarta.servlet.DispatcherType; -import jakarta.servlet.Filter; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.websocket.DeploymentException; -import jakarta.websocket.server.ServerContainer; -import jakarta.websocket.server.ServerEndpoint; -import org.eclipse.jetty.ee10.websocket.servlet.WebSocketUpgradeFilter; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; -import org.springframework.boot.test.context.runner.WebApplicationContextRunner; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.testsupport.classpath.ForkedClassPath; -import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories; -import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; -import org.springframework.boot.web.server.WebServer; -import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor; -import org.springframework.boot.web.servlet.AbstractFilterRegistrationBean; -import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.boot.web.servlet.ServletContextInitializer; -import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; -import org.springframework.boot.web.servlet.server.ServletWebServerFactory; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.Ordered; -import org.springframework.http.HttpStatus; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link WebSocketServletAutoConfiguration} - * - * @author Andy Wilkinson - */ -@DirtiesUrlFactories -class WebSocketServletAutoConfigurationTests { - - @ParameterizedTest(name = "{0}") - @MethodSource("testConfiguration") - @ForkedClassPath - void serverContainerIsAvailableFromTheServletContext(String server, Class... configuration) { - try (AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext( - configuration)) { - Object serverContainer = context.getServletContext() - .getAttribute("jakarta.websocket.server.ServerContainer"); - assertThat(serverContainer).isInstanceOf(ServerContainer.class); - } - } - - @ParameterizedTest(name = "{0}") - @MethodSource("testConfiguration") - @ForkedClassPath - void webSocketUpgradeDoesNotPreventAFilterFromRejectingTheRequest(String server, Class... configuration) - throws DeploymentException { - try (AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext( - configuration)) { - ServerContainer serverContainer = (ServerContainer) context.getServletContext() - .getAttribute("jakarta.websocket.server.ServerContainer"); - serverContainer.addEndpoint(TestEndpoint.class); - WebServer webServer = context.getWebServer(); - int port = webServer.getPort(); - TestRestTemplate rest = new TestRestTemplate(); - RequestEntity request = RequestEntity.get("http://localhost:" + port) - .header("Upgrade", "websocket") - .header("Connection", "upgrade") - .header("Sec-WebSocket-Version", "13") - .header("Sec-WebSocket-Key", "key") - .build(); - ResponseEntity response = rest.exchange(request, Void.class); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); - } - } - - @Test - void jettyWebSocketUpgradeFilterIsAddedToServletContextOfJettyServer() { - try (AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext( - JettyConfiguration.class, WebSocketServletAutoConfiguration.JettyWebSocketConfiguration.class)) { - assertThat(context.getServletContext().getFilterRegistration(WebSocketUpgradeFilter.class.getName())) - .isNotNull(); - } - } - - @Test - void jettyWebSocketUpgradeFilterIsNotAddedToServletContextOfTomcatServer() { - try (AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext( - TomcatConfiguration.class, WebSocketServletAutoConfiguration.JettyWebSocketConfiguration.class)) { - assertThat(context.getServletContext().getFilterRegistration(WebSocketUpgradeFilter.class.getName())) - .isNull(); - } - } - - @Test - @SuppressWarnings("rawtypes") - void jettyWebSocketUpgradeFilterIsNotExposedAsABean() { - new WebApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(JettyConfiguration.class, - WebSocketServletAutoConfiguration.JettyWebSocketConfiguration.class)) - .run((context) -> { - Map filters = context.getBeansOfType(Filter.class); - assertThat(filters.values()).noneMatch(WebSocketUpgradeFilter.class::isInstance); - Map filterRegistrations = context - .getBeansOfType(AbstractFilterRegistrationBean.class); - assertThat(filterRegistrations.values()).extracting(AbstractFilterRegistrationBean::getFilter) - .noneMatch(WebSocketUpgradeFilter.class::isInstance); - }); - } - - @Test - void jettyWebSocketUpgradeFilterServletContextInitializerBacksOffWhenBeanWithSameNameIsDefined() { - try (AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext( - JettyConfiguration.class, CustomWebSocketUpgradeFilterServletContextInitializerConfiguration.class, - WebSocketServletAutoConfiguration.JettyWebSocketConfiguration.class)) { - BeanDefinition definition = context.getBeanFactory() - .getBeanDefinition("websocketUpgradeFilterServletContextInitializer"); - assertThat(definition.getFactoryBeanName()) - .contains("CustomWebSocketUpgradeFilterServletContextInitializerConfiguration"); - } - } - - static Stream testConfiguration() { - String response = "Tomcat"; - return Stream.of( - Arguments.of("Jetty", - new Class[] { JettyConfiguration.class, DispatcherServletAutoConfiguration.class, - WebSocketServletAutoConfiguration.JettyWebSocketConfiguration.class }), - Arguments.of(response, - new Class[] { TomcatConfiguration.class, DispatcherServletAutoConfiguration.class, - WebSocketServletAutoConfiguration.TomcatWebSocketConfiguration.class })); - } - - @Configuration(proxyBeanMethods = false) - static class CommonConfiguration { - - @Bean - FilterRegistrationBean unauthorizedFilter() { - FilterRegistrationBean registration = new FilterRegistrationBean<>(new Filter() { - - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) - throws IOException, ServletException { - ((HttpServletResponse) response).sendError(HttpStatus.UNAUTHORIZED.value()); - } - - }); - registration.setOrder(Ordered.HIGHEST_PRECEDENCE); - registration.addUrlPatterns("/*"); - registration.setDispatcherTypes(DispatcherType.REQUEST); - return registration; - } - - @Bean - static WebServerFactoryCustomizerBeanPostProcessor servletWebServerCustomizerBeanPostProcessor() { - return new WebServerFactoryCustomizerBeanPostProcessor(); - } - - } - - @Configuration(proxyBeanMethods = false) - static class TomcatConfiguration extends CommonConfiguration { - - @Bean - ServletWebServerFactory webServerFactory() { - TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(); - factory.setPort(0); - return factory; - } - - } - - @Configuration(proxyBeanMethods = false) - static class JettyConfiguration extends CommonConfiguration { - - @Bean - ServletWebServerFactory webServerFactory() { - JettyServletWebServerFactory JettyServletWebServerFactory = new JettyServletWebServerFactory(); - JettyServletWebServerFactory.setPort(0); - return JettyServletWebServerFactory; - } - - } - - @Configuration(proxyBeanMethods = false) - static class CustomWebSocketUpgradeFilterServletContextInitializerConfiguration { - - @Bean - ServletContextInitializer websocketUpgradeFilterServletContextInitializer() { - return (servletContext) -> { - - }; - } - - } - - @ServerEndpoint("/") - public static class TestEndpoint { - - } - -} diff --git a/spring-boot-project/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfigurationTests.java b/spring-boot-project/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfigurationTests.java index 478e6ff283..d127533bea 100644 --- a/spring-boot-project/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,7 +36,7 @@ import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration; import org.springframework.boot.autoconfigure.web.WebProperties; import org.springframework.boot.autoconfigure.web.WebProperties.Resources; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.devtools.classpath.ClassPathChangedEvent; import org.springframework.boot.devtools.classpath.ClassPathFileSystemWatcher; import org.springframework.boot.devtools.livereload.LiveReloadServer; @@ -44,7 +44,7 @@ import org.springframework.boot.devtools.restart.FailureHandler; import org.springframework.boot.devtools.restart.MockRestartInitializer; import org.springframework.boot.devtools.restart.MockRestarter; import org.springframework.boot.devtools.restart.Restarter; -import org.springframework.boot.web.embedded.tomcat.TomcatWebServer; +import org.springframework.boot.web.server.tomcat.TomcatWebServer; import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; @@ -258,14 +258,14 @@ class LocalDevToolsAutoConfigurationTests { } @Configuration(proxyBeanMethods = false) - @Import({ ServletWebServerFactoryAutoConfiguration.class, LocalDevToolsAutoConfiguration.class, + @Import({ TomcatServletWebServerAutoConfiguration.class, LocalDevToolsAutoConfiguration.class, FreeMarkerAutoConfiguration.class }) static class Config { } @Configuration(proxyBeanMethods = false) - @ImportAutoConfiguration({ ServletWebServerFactoryAutoConfiguration.class, LocalDevToolsAutoConfiguration.class, + @ImportAutoConfiguration({ TomcatServletWebServerAutoConfiguration.class, LocalDevToolsAutoConfiguration.class, FreeMarkerAutoConfiguration.class }) static class ConfigWithMockLiveReload { @@ -277,7 +277,7 @@ class LocalDevToolsAutoConfigurationTests { } @Configuration(proxyBeanMethods = false) - @Import({ ServletWebServerFactoryAutoConfiguration.class, LocalDevToolsAutoConfiguration.class, + @Import({ TomcatServletWebServerAutoConfiguration.class, LocalDevToolsAutoConfiguration.class, WebProperties.class }) static class WebResourcesConfig { diff --git a/spring-boot-project/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/remote/client/RemoteClientConfigurationTests.java b/spring-boot-project/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/remote/client/RemoteClientConfigurationTests.java index 8b024eee90..ba9c277069 100644 --- a/spring-boot-project/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/remote/client/RemoteClientConfigurationTests.java +++ b/spring-boot-project/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/remote/client/RemoteClientConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,7 +40,7 @@ import org.springframework.boot.devtools.restart.RestartScopeInitializer; import org.springframework.boot.test.system.CapturedOutput; import org.springframework.boot.test.system.OutputCaptureExtension; import org.springframework.boot.test.util.TestPropertyValues; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/actuator/cloudfoundry/customcontextpath/MyCloudFoundryConfiguration.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/actuator/cloudfoundry/customcontextpath/MyCloudFoundryConfiguration.java index e209c782dd..ca332c1ef2 100644 --- a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/actuator/cloudfoundry/customcontextpath/MyCloudFoundryConfiguration.java +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/actuator/cloudfoundry/customcontextpath/MyCloudFoundryConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,8 +30,8 @@ import org.apache.catalina.Host; import org.apache.catalina.core.StandardContext; import org.apache.catalina.startup.Tomcat; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; -import org.springframework.boot.web.servlet.ServletContextInitializer; +import org.springframework.boot.web.server.servlet.ServletContextInitializer; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/webserver/configure/MyTomcatWebServerCustomizer.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/webserver/configure/MyTomcatWebServerCustomizer.java index 14df9fc80b..823e799216 100644 --- a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/webserver/configure/MyTomcatWebServerCustomizer.java +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/webserver/configure/MyTomcatWebServerCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,8 +16,8 @@ package org.springframework.boot.docs.howto.webserver.configure; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.stereotype.Component; @Component diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/webserver/enablemultipleconnectorsintomcat/MyTomcatConfiguration.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/webserver/enablemultipleconnectorsintomcat/MyTomcatConfiguration.java index e78dfed919..40eb69c3fb 100644 --- a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/webserver/enablemultipleconnectorsintomcat/MyTomcatConfiguration.java +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/webserver/enablemultipleconnectorsintomcat/MyTomcatConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,8 +18,8 @@ package org.springframework.boot.docs.howto.webserver.enablemultipleconnectorsin import org.apache.catalina.connector.Connector; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -28,7 +28,7 @@ public class MyTomcatConfiguration { @Bean public WebServerFactoryCustomizer connectorCustomizer() { - return (tomcat) -> tomcat.addAdditionalTomcatConnectors(createConnector()); + return (tomcat) -> tomcat.addAdditionalConnectors(createConnector()); } private Connector createConnector() { diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/webserver/enablemultiplelistenersinundertow/MyUndertowConfiguration.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/webserver/enablemultiplelistenersinundertow/MyUndertowConfiguration.java index 35ab674a03..e7da31eb0b 100644 --- a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/webserver/enablemultiplelistenersinundertow/MyUndertowConfiguration.java +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/webserver/enablemultiplelistenersinundertow/MyUndertowConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,8 +18,8 @@ package org.springframework.boot.docs.howto.webserver.enablemultiplelistenersinu import io.undertow.Undertow.Builder; -import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.servlet.undertow.UndertowServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/utilities/testresttemplate/MySpringBootTestsConfiguration.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/utilities/testresttemplate/MySpringBootTestsConfiguration.java index 6e88f20eeb..d6f357daea 100644 --- a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/utilities/testresttemplate/MySpringBootTestsConfiguration.java +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/utilities/testresttemplate/MySpringBootTestsConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,14 +22,14 @@ import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @SpringBootConfiguration(proxyBeanMethods = false) -@ImportAutoConfiguration({ ServletWebServerFactoryAutoConfiguration.class, DispatcherServletAutoConfiguration.class, +@ImportAutoConfiguration({ TomcatServletWebServerAutoConfiguration.class, DispatcherServletAutoConfiguration.class, JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class }) public class MySpringBootTestsConfiguration { diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/web/reactive/reactiveserver/customizing/programmatic/MyNettyWebServerFactoryCustomizer.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/web/reactive/reactiveserver/customizing/programmatic/MyNettyWebServerFactoryCustomizer.java index 71856eaf64..045ba95155 100644 --- a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/web/reactive/reactiveserver/customizing/programmatic/MyNettyWebServerFactoryCustomizer.java +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/web/reactive/reactiveserver/customizing/programmatic/MyNettyWebServerFactoryCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,8 +18,8 @@ package org.springframework.boot.docs.web.reactive.reactiveserver.customizing.pr import java.time.Duration; -import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.reactive.netty.NettyReactiveWebServerFactory; import org.springframework.stereotype.Component; @Component diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/web/reactive/reactiveserver/customizing/programmatic/MyWebServerFactoryCustomizer.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/web/reactive/reactiveserver/customizing/programmatic/MyWebServerFactoryCustomizer.java index da9d692489..19ed125480 100644 --- a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/web/reactive/reactiveserver/customizing/programmatic/MyWebServerFactoryCustomizer.java +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/web/reactive/reactiveserver/customizing/programmatic/MyWebServerFactoryCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,8 +16,8 @@ package org.springframework.boot.docs.web.reactive.reactiveserver.customizing.programmatic; -import org.springframework.boot.web.reactive.server.ConfigurableReactiveWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.reactive.ConfigurableReactiveWebServerFactory; import org.springframework.stereotype.Component; @Component diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/web/servlet/embeddedcontainer/customizing/programmatic/MyTomcatWebServerFactoryCustomizer.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/web/servlet/embeddedcontainer/customizing/programmatic/MyTomcatWebServerFactoryCustomizer.java index 7583a91227..3cebffa9a7 100644 --- a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/web/servlet/embeddedcontainer/customizing/programmatic/MyTomcatWebServerFactoryCustomizer.java +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/web/servlet/embeddedcontainer/customizing/programmatic/MyTomcatWebServerFactoryCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,8 +18,8 @@ package org.springframework.boot.docs.web.servlet.embeddedcontainer.customizing. import java.time.Duration; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.stereotype.Component; @Component diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/web/servlet/embeddedcontainer/customizing/programmatic/MyWebServerFactoryCustomizer.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/web/servlet/embeddedcontainer/customizing/programmatic/MyWebServerFactoryCustomizer.java index cd4a2acf9f..3f20b78144 100644 --- a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/web/servlet/embeddedcontainer/customizing/programmatic/MyWebServerFactoryCustomizer.java +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/web/servlet/embeddedcontainer/customizing/programmatic/MyWebServerFactoryCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ package org.springframework.boot.docs.web.servlet.embeddedcontainer.customizing.programmatic; import org.springframework.boot.web.server.WebServerFactoryCustomizer; -import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; +import org.springframework.boot.web.server.servlet.ConfigurableServletWebServerFactory; import org.springframework.stereotype.Component; @Component diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/web/servlet/embeddedcontainer/customizing/samesite/MySameSiteConfiguration.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/web/servlet/embeddedcontainer/customizing/samesite/MySameSiteConfiguration.java index 149d1adcc9..d848ae52f5 100644 --- a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/web/servlet/embeddedcontainer/customizing/samesite/MySameSiteConfiguration.java +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/web/servlet/embeddedcontainer/customizing/samesite/MySameSiteConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,7 @@ package org.springframework.boot.docs.web.servlet.embeddedcontainer.customizing.samesite; -import org.springframework.boot.web.servlet.server.CookieSameSiteSupplier; +import org.springframework.boot.web.server.servlet.CookieSameSiteSupplier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/actuator/cloudfoundry/customcontextpath/MyCloudFoundryConfiguration.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/actuator/cloudfoundry/customcontextpath/MyCloudFoundryConfiguration.kt index 2a4efd369c..d4372cc23d 100644 --- a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/actuator/cloudfoundry/customcontextpath/MyCloudFoundryConfiguration.kt +++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/actuator/cloudfoundry/customcontextpath/MyCloudFoundryConfiguration.kt @@ -26,8 +26,8 @@ import jakarta.servlet.ServletResponse import org.apache.catalina.Host import org.apache.catalina.core.StandardContext import org.apache.catalina.startup.Tomcat.FixContextListener -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory -import org.springframework.boot.web.servlet.ServletContextInitializer +import org.springframework.boot.web.server.servlet.ServletContextInitializer +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import java.io.IOException diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/webserver/configure/MyTomcatWebServerCustomizer.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/webserver/configure/MyTomcatWebServerCustomizer.kt index 5f4549c579..e78d2c39a5 100644 --- a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/webserver/configure/MyTomcatWebServerCustomizer.kt +++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/webserver/configure/MyTomcatWebServerCustomizer.kt @@ -16,8 +16,8 @@ package org.springframework.boot.docs.howto.webserver.configure -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory import org.springframework.boot.web.server.WebServerFactoryCustomizer +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory import org.springframework.stereotype.Component @Component diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/webserver/enablemultipleconnectorsintomcat/MyTomcatConfiguration.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/webserver/enablemultipleconnectorsintomcat/MyTomcatConfiguration.kt index 437f24de04..1d670f03cd 100644 --- a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/webserver/enablemultipleconnectorsintomcat/MyTomcatConfiguration.kt +++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/webserver/enablemultipleconnectorsintomcat/MyTomcatConfiguration.kt @@ -17,8 +17,8 @@ package org.springframework.boot.docs.howto.webserver.enablemultipleconnectorsintomcat import org.apache.catalina.connector.Connector -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory import org.springframework.boot.web.server.WebServerFactoryCustomizer +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration @@ -28,9 +28,7 @@ class MyTomcatConfiguration { @Bean fun connectorCustomizer(): WebServerFactoryCustomizer { return WebServerFactoryCustomizer { tomcat: TomcatServletWebServerFactory -> - tomcat.addAdditionalTomcatConnectors( - createConnector() - ) + tomcat.addAdditionalConnectors(createConnector()) } } diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/webserver/enablemultiplelistenersinundertow/MyUndertowConfiguration.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/webserver/enablemultiplelistenersinundertow/MyUndertowConfiguration.kt index 05e5f38d7a..66dd04acd1 100644 --- a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/webserver/enablemultiplelistenersinundertow/MyUndertowConfiguration.kt +++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/webserver/enablemultiplelistenersinundertow/MyUndertowConfiguration.kt @@ -17,9 +17,9 @@ package org.springframework.boot.docs.howto.webserver.enablemultiplelistenersinundertow import io.undertow.Undertow -import org.springframework.boot.web.embedded.undertow.UndertowBuilderCustomizer -import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory import org.springframework.boot.web.server.WebServerFactoryCustomizer +import org.springframework.boot.web.server.undertow.UndertowBuilderCustomizer +import org.springframework.boot.web.server.servlet.undertow.UndertowServletWebServerFactory import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/utilities/testresttemplate/MySpringBootTestsConfiguration.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/utilities/testresttemplate/MySpringBootTestsConfiguration.kt index 9fca0e73bf..98060d19cc 100644 --- a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/utilities/testresttemplate/MySpringBootTestsConfiguration.kt +++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/utilities/testresttemplate/MySpringBootTestsConfiguration.kt @@ -20,8 +20,8 @@ import org.springframework.boot.SpringBootConfiguration import org.springframework.boot.autoconfigure.ImportAutoConfiguration import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController @@ -29,7 +29,7 @@ import java.net.URI @SpringBootConfiguration(proxyBeanMethods = false) @ImportAutoConfiguration( - ServletWebServerFactoryAutoConfiguration::class, + TomcatServletWebServerAutoConfiguration::class, DispatcherServletAutoConfiguration::class, JacksonAutoConfiguration::class, HttpMessageConvertersAutoConfiguration::class diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/web/reactive/reactiveserver/customizing/programmatic/MyNettyWebServerFactoryCustomizer.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/web/reactive/reactiveserver/customizing/programmatic/MyNettyWebServerFactoryCustomizer.kt index d7bd5f4d19..76a8f6f502 100644 --- a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/web/reactive/reactiveserver/customizing/programmatic/MyNettyWebServerFactoryCustomizer.kt +++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/web/reactive/reactiveserver/customizing/programmatic/MyNettyWebServerFactoryCustomizer.kt @@ -16,8 +16,8 @@ package org.springframework.boot.docs.web.reactive.reactiveserver.customizing.programmatic -import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory import org.springframework.boot.web.server.WebServerFactoryCustomizer +import org.springframework.boot.web.server.reactive.netty.NettyReactiveWebServerFactory import org.springframework.stereotype.Component import java.time.Duration diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/web/reactive/reactiveserver/customizing/programmatic/MyWebServerFactoryCustomizer.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/web/reactive/reactiveserver/customizing/programmatic/MyWebServerFactoryCustomizer.kt index fc48c79f97..16d42cbccd 100644 --- a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/web/reactive/reactiveserver/customizing/programmatic/MyWebServerFactoryCustomizer.kt +++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/web/reactive/reactiveserver/customizing/programmatic/MyWebServerFactoryCustomizer.kt @@ -17,7 +17,7 @@ package org.springframework.boot.docs.web.reactive.reactiveserver.customizing.programmatic import org.springframework.boot.web.server.WebServerFactoryCustomizer -import org.springframework.boot.web.reactive.server.ConfigurableReactiveWebServerFactory +import org.springframework.boot.web.server.reactive.ConfigurableReactiveWebServerFactory import org.springframework.stereotype.Component @Component diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/web/servlet/embeddedcontainer/customizing/programmatic/MyTomcatWebServerFactoryCustomizer.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/web/servlet/embeddedcontainer/customizing/programmatic/MyTomcatWebServerFactoryCustomizer.kt index e3727493b4..e823211832 100644 --- a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/web/servlet/embeddedcontainer/customizing/programmatic/MyTomcatWebServerFactoryCustomizer.kt +++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/web/servlet/embeddedcontainer/customizing/programmatic/MyTomcatWebServerFactoryCustomizer.kt @@ -16,8 +16,8 @@ package org.springframework.boot.docs.web.servlet.embeddedcontainer.customizing.programmatic -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory import org.springframework.boot.web.server.WebServerFactoryCustomizer +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory import org.springframework.stereotype.Component import java.time.Duration diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/web/servlet/embeddedcontainer/customizing/programmatic/MyWebServerFactoryCustomizer.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/web/servlet/embeddedcontainer/customizing/programmatic/MyWebServerFactoryCustomizer.kt index 5acfb75926..55f0225828 100644 --- a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/web/servlet/embeddedcontainer/customizing/programmatic/MyWebServerFactoryCustomizer.kt +++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/web/servlet/embeddedcontainer/customizing/programmatic/MyWebServerFactoryCustomizer.kt @@ -16,8 +16,8 @@ package org.springframework.boot.docs.web.servlet.embeddedcontainer.customizing.programmatic +import org.springframework.boot.web.server.servlet.ConfigurableServletWebServerFactory import org.springframework.boot.web.server.WebServerFactoryCustomizer -import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory import org.springframework.stereotype.Component @Component diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/web/servlet/embeddedcontainer/customizing/samesite/MySameSiteConfiguration.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/web/servlet/embeddedcontainer/customizing/samesite/MySameSiteConfiguration.kt index fe2b89f8d1..ecc0578d43 100644 --- a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/web/servlet/embeddedcontainer/customizing/samesite/MySameSiteConfiguration.kt +++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/web/servlet/embeddedcontainer/customizing/samesite/MySameSiteConfiguration.kt @@ -16,7 +16,7 @@ package org.springframework.boot.docs.web.servlet.embeddedcontainer.customizing.samesite -import org.springframework.boot.web.servlet.server.CookieSameSiteSupplier +import org.springframework.boot.web.server.servlet.CookieSameSiteSupplier import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/TestRestTemplateContextCustomizer.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/TestRestTemplateContextCustomizer.java index fa7cb7cbc4..11bf7fef35 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/TestRestTemplateContextCustomizer.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/TestRestTemplateContextCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,7 +32,7 @@ import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate.HttpClientOption; import org.springframework.boot.web.client.RestTemplateBuilder; -import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactory; +import org.springframework.boot.web.server.AbstractConfigurableWebServerFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ConfigurableApplicationContext; @@ -149,8 +149,8 @@ class TestRestTemplateContextCustomizer implements ContextCustomizer { private boolean isSslEnabled(ApplicationContext context) { try { - AbstractServletWebServerFactory webServerFactory = context - .getBean(AbstractServletWebServerFactory.class); + AbstractConfigurableWebServerFactory webServerFactory = context + .getBean(AbstractConfigurableWebServerFactory.class); return webServerFactory.getSsl() != null && webServerFactory.getSsl().isEnabled(); } catch (NoSuchBeanDefinitionException ex) { diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/reactive/server/WebTestClientContextCustomizer.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/reactive/server/WebTestClientContextCustomizer.java index f7f18d2c14..2ade67c31c 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/reactive/server/WebTestClientContextCustomizer.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/reactive/server/WebTestClientContextCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,7 +34,7 @@ import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.boot.WebApplicationType; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.web.codec.CodecCustomizer; -import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.AbstractReactiveWebServerFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ConfigurableApplicationContext; diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/AbstractSpringBootTestEmbeddedReactiveWebEnvironmentTests.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/AbstractSpringBootTestEmbeddedReactiveWebEnvironmentTests.java index 08858cbca4..52da84380f 100644 --- a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/AbstractSpringBootTestEmbeddedReactiveWebEnvironmentTests.java +++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/AbstractSpringBootTestEmbeddedReactiveWebEnvironmentTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,9 +25,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory; import org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext; -import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.ReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.tomcat.TomcatReactiveWebServerFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/AbstractSpringBootTestWebServerWebEnvironmentTests.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/AbstractSpringBootTestWebServerWebEnvironmentTests.java index 1921a66862..9a30cdb8d8 100644 --- a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/AbstractSpringBootTestWebServerWebEnvironmentTests.java +++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/AbstractSpringBootTestWebServerWebEnvironmentTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,8 +23,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; -import org.springframework.boot.web.servlet.server.ServletWebServerFactory; +import org.springframework.boot.web.server.servlet.ServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/graphql/tester/HttpGraphQlTesterContextCustomizerIntegrationTests.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/graphql/tester/HttpGraphQlTesterContextCustomizerIntegrationTests.java index b66eec19be..8fc226721c 100644 --- a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/graphql/tester/HttpGraphQlTesterContextCustomizerIntegrationTests.java +++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/graphql/tester/HttpGraphQlTesterContextCustomizerIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ import reactor.core.publisher.Mono; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.tomcat.TomcatReactiveWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.buffer.DefaultDataBufferFactory; diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/graphql/tester/HttpGraphQlTesterContextCustomizerWithCustomBasePathTests.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/graphql/tester/HttpGraphQlTesterContextCustomizerWithCustomBasePathTests.java index f7167d07e1..cff9e6492c 100644 --- a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/graphql/tester/HttpGraphQlTesterContextCustomizerWithCustomBasePathTests.java +++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/graphql/tester/HttpGraphQlTesterContextCustomizerWithCustomBasePathTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ import reactor.core.publisher.Mono; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.tomcat.TomcatReactiveWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.buffer.DefaultDataBufferFactory; diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/graphql/tester/HttpGraphQlTesterContextCustomizerWithCustomContextPathTests.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/graphql/tester/HttpGraphQlTesterContextCustomizerWithCustomContextPathTests.java index fec60ac442..47df5fe13a 100644 --- a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/graphql/tester/HttpGraphQlTesterContextCustomizerWithCustomContextPathTests.java +++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/graphql/tester/HttpGraphQlTesterContextCustomizerWithCustomContextPathTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/client/TestRestTemplateContextCustomizerIntegrationTests.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/client/TestRestTemplateContextCustomizerIntegrationTests.java index 5a25577163..53d1877223 100644 --- a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/client/TestRestTemplateContextCustomizerIntegrationTests.java +++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/client/TestRestTemplateContextCustomizerIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,7 +28,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/client/TestRestTemplateContextCustomizerWithFactoryBeanTests.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/client/TestRestTemplateContextCustomizerWithFactoryBeanTests.java index 803e4a0cbe..e1fff67065 100644 --- a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/client/TestRestTemplateContextCustomizerWithFactoryBeanTests.java +++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/client/TestRestTemplateContextCustomizerWithFactoryBeanTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,7 +21,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/client/TestRestTemplateContextCustomizerWithOverrideIntegrationTests.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/client/TestRestTemplateContextCustomizerWithOverrideIntegrationTests.java index 5a3a09cf18..58300e8f23 100644 --- a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/client/TestRestTemplateContextCustomizerWithOverrideIntegrationTests.java +++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/client/TestRestTemplateContextCustomizerWithOverrideIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,7 +28,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/reactive/server/WebTestClientContextCustomizerIntegrationTests.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/reactive/server/WebTestClientContextCustomizerIntegrationTests.java index ee02eaff23..aa949d75fa 100644 --- a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/reactive/server/WebTestClientContextCustomizerIntegrationTests.java +++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/reactive/server/WebTestClientContextCustomizerIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,7 +22,7 @@ import reactor.core.publisher.Mono; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.tomcat.TomcatReactiveWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/reactive/server/WebTestClientContextCustomizerWithCustomBasePathTests.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/reactive/server/WebTestClientContextCustomizerWithCustomBasePathTests.java index c1ef48bf3d..b102f5fe93 100644 --- a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/reactive/server/WebTestClientContextCustomizerWithCustomBasePathTests.java +++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/reactive/server/WebTestClientContextCustomizerWithCustomBasePathTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ import reactor.core.publisher.Mono; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.tomcat.TomcatReactiveWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.buffer.DefaultDataBufferFactory; diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/reactive/server/WebTestClientContextCustomizerWithCustomContextPathTests.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/reactive/server/WebTestClientContextCustomizerWithCustomContextPathTests.java index 9df89b8752..7d7bb48feb 100644 --- a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/reactive/server/WebTestClientContextCustomizerWithCustomContextPathTests.java +++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/reactive/server/WebTestClientContextCustomizerWithCustomContextPathTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/reactive/server/WebTestClientContextCustomizerWithOverrideIntegrationTests.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/reactive/server/WebTestClientContextCustomizerWithOverrideIntegrationTests.java index da28bb75ac..2d8ecb1a0f 100644 --- a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/reactive/server/WebTestClientContextCustomizerWithOverrideIntegrationTests.java +++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/reactive/server/WebTestClientContextCustomizerWithOverrideIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,7 +22,7 @@ import reactor.core.publisher.Mono; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.tomcat.TomcatReactiveWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/rsocket/netty/NettyRSocketServerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/rsocket/netty/NettyRSocketServerFactory.java index 5c040672c0..b0c21d5e88 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/rsocket/netty/NettyRSocketServerFactory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/rsocket/netty/NettyRSocketServerFactory.java @@ -43,11 +43,11 @@ import org.springframework.boot.rsocket.server.RSocketServerCustomizer; import org.springframework.boot.rsocket.server.RSocketServerFactory; import org.springframework.boot.ssl.SslBundle; import org.springframework.boot.ssl.SslBundles; -import org.springframework.boot.web.embedded.netty.SslServerCustomizer; import org.springframework.boot.web.server.Ssl; import org.springframework.boot.web.server.Ssl.ClientAuth; import org.springframework.boot.web.server.Ssl.ServerNameSslBundle; import org.springframework.boot.web.server.WebServerSslBundle; +import org.springframework.boot.web.server.reactive.netty.SslServerCustomizer; import org.springframework.http.client.ReactorResourceFactory; import org.springframework.util.Assert; import org.springframework.util.unit.DataSize; @@ -223,7 +223,7 @@ public class NettyRSocketServerFactory implements RSocketServerFactory, Configur } private static final class TcpSslServerCustomizer - extends org.springframework.boot.web.embedded.netty.SslServerCustomizer { + extends org.springframework.boot.web.server.reactive.netty.SslServerCustomizer { private final SslBundle sslBundle; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowReactiveWebServerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowReactiveWebServerFactory.java deleted file mode 100644 index 4ef3fe440b..0000000000 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowReactiveWebServerFactory.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright 2012-2025 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.web.embedded.undertow; - -import java.io.File; -import java.util.Collection; -import java.util.List; - -import io.undertow.Undertow; - -import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactory; -import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; -import org.springframework.boot.web.server.WebServer; -import org.springframework.http.server.reactive.UndertowHttpHandlerAdapter; - -/** - * {@link ReactiveWebServerFactory} that can be used to create {@link UndertowWebServer}s. - * - * @author Brian Clozel - * @author Scott Frederick - * @since 2.0.0 - */ -public class UndertowReactiveWebServerFactory extends AbstractReactiveWebServerFactory - implements ConfigurableUndertowWebServerFactory { - - private final UndertowWebServerFactoryDelegate delegate = new UndertowWebServerFactoryDelegate(); - - /** - * Create a new {@link UndertowReactiveWebServerFactory} instance. - */ - public UndertowReactiveWebServerFactory() { - } - - /** - * Create a new {@link UndertowReactiveWebServerFactory} that listens for requests - * using the specified port. - * @param port the port to listen on - */ - public UndertowReactiveWebServerFactory(int port) { - super(port); - } - - @Override - public void setBuilderCustomizers(Collection customizers) { - this.delegate.setBuilderCustomizers(customizers); - } - - @Override - public void addBuilderCustomizers(UndertowBuilderCustomizer... customizers) { - this.delegate.addBuilderCustomizers(customizers); - } - - /** - * Returns a mutable collection of the {@link UndertowBuilderCustomizer}s that will be - * applied to the Undertow {@link io.undertow.Undertow.Builder Builder}. - * @return the customizers that will be applied - */ - public Collection getBuilderCustomizers() { - return this.delegate.getBuilderCustomizers(); - } - - @Override - public void setBufferSize(Integer bufferSize) { - this.delegate.setBufferSize(bufferSize); - } - - @Override - public void setIoThreads(Integer ioThreads) { - this.delegate.setIoThreads(ioThreads); - } - - @Override - public void setWorkerThreads(Integer workerThreads) { - this.delegate.setWorkerThreads(workerThreads); - } - - @Override - public void setUseDirectBuffers(Boolean directBuffers) { - this.delegate.setUseDirectBuffers(directBuffers); - } - - @Override - public void setUseForwardHeaders(boolean useForwardHeaders) { - this.delegate.setUseForwardHeaders(useForwardHeaders); - } - - protected final boolean isUseForwardHeaders() { - return this.delegate.isUseForwardHeaders(); - } - - @Override - public void setAccessLogDirectory(File accessLogDirectory) { - this.delegate.setAccessLogDirectory(accessLogDirectory); - } - - @Override - public void setAccessLogPattern(String accessLogPattern) { - this.delegate.setAccessLogPattern(accessLogPattern); - } - - /** - * Returns the access log prefix. - * @return the access log prefix - * @since 3.5.0 - */ - public String getAccessLogPrefix() { - return this.delegate.getAccessLogPrefix(); - } - - @Override - public void setAccessLogPrefix(String accessLogPrefix) { - this.delegate.setAccessLogPrefix(accessLogPrefix); - } - - @Override - public void setAccessLogSuffix(String accessLogSuffix) { - this.delegate.setAccessLogSuffix(accessLogSuffix); - } - - public boolean isAccessLogEnabled() { - return this.delegate.isAccessLogEnabled(); - } - - @Override - public void setAccessLogEnabled(boolean accessLogEnabled) { - this.delegate.setAccessLogEnabled(accessLogEnabled); - } - - @Override - public void setAccessLogRotate(boolean accessLogRotate) { - this.delegate.setAccessLogRotate(accessLogRotate); - } - - @Override - public WebServer getWebServer(org.springframework.http.server.reactive.HttpHandler httpHandler) { - Undertow.Builder builder = this.delegate.createBuilder(this, this::getSslBundle, this::getServerNameSslBundles); - List httpHandlerFactories = this.delegate.createHttpHandlerFactories(this, - (next) -> new UndertowHttpHandlerAdapter(httpHandler)); - return new UndertowWebServer(builder, httpHandlerFactories, getPort() >= 0); - } - -} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/context/ReactiveWebServerApplicationContext.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/context/ReactiveWebServerApplicationContext.java index 9e6bef5219..170f197ca9 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/context/ReactiveWebServerApplicationContext.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/context/ReactiveWebServerApplicationContext.java @@ -24,8 +24,8 @@ import org.springframework.boot.availability.ReadinessState; import org.springframework.boot.web.context.ConfigurableWebServerApplicationContext; import org.springframework.boot.web.context.MissingWebServerFactoryBeanException; import org.springframework.boot.web.context.WebServerGracefulShutdownLifecycle; -import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.reactive.ReactiveWebServerFactory; import org.springframework.context.ApplicationContextException; import org.springframework.core.metrics.StartupStep; import org.springframework.http.server.reactive.HttpHandler; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/context/WebServerManager.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/context/WebServerManager.java index 65f9e145c9..7c323271a1 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/context/WebServerManager.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/context/WebServerManager.java @@ -20,9 +20,9 @@ import java.util.function.Supplier; import reactor.core.publisher.Mono; -import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; import org.springframework.boot.web.server.GracefulShutdownCallback; import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.reactive.ReactiveWebServerFactory; import org.springframework.http.server.reactive.HttpHandler; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/WebServerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/WebServerFactory.java index b393f3263b..e5a3a976fe 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/WebServerFactory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/WebServerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,8 +22,8 @@ package org.springframework.boot.web.server; * @author Phillip Webb * @since 2.0.0 * @see WebServer - * @see org.springframework.boot.web.servlet.server.ServletWebServerFactory - * @see org.springframework.boot.web.reactive.server.ReactiveWebServerFactory + * @see org.springframework.boot.web.server.servlet.ServletWebServerFactory + * @see org.springframework.boot.web.server.reactive.ReactiveWebServerFactory */ public interface WebServerFactory { diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/ConfigurableJettyWebServerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/ConfigurableJettyWebServerFactory.java similarity index 90% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/ConfigurableJettyWebServerFactory.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/ConfigurableJettyWebServerFactory.java index d92502ac9a..a6e34dd799 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/ConfigurableJettyWebServerFactory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/ConfigurableJettyWebServerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.jetty; +package org.springframework.boot.web.server.jetty; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.util.thread.ThreadPool; @@ -26,9 +26,7 @@ import org.springframework.boot.web.server.ConfigurableWebServerFactory; * * @author Brian Clozel * @author Moritz Halbritter - * @since 2.0.0 - * @see JettyServletWebServerFactory - * @see JettyReactiveWebServerFactory + * @since 4.0.0 */ public interface ConfigurableJettyWebServerFactory extends ConfigurableWebServerFactory { @@ -67,7 +65,7 @@ public interface ConfigurableJettyWebServerFactory extends ConfigurableWebServer /** * Sets the maximum number of concurrent connections. * @param maxConnections the maximum number of concurrent connections - * @since 3.2.0 + * @since 4.0.0 */ void setMaxConnections(int maxConnections); diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/ForwardHeadersCustomizer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/ForwardHeadersCustomizer.java similarity index 87% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/ForwardHeadersCustomizer.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/ForwardHeadersCustomizer.java index f4d73410bf..08ee1aadbe 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/ForwardHeadersCustomizer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/ForwardHeadersCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.jetty; +package org.springframework.boot.web.server.jetty; import org.eclipse.jetty.server.ConnectionFactory; import org.eclipse.jetty.server.Connector; @@ -26,8 +26,9 @@ import org.eclipse.jetty.server.Server; * {@link JettyServerCustomizer} to add {@link ForwardedRequestCustomizer}. * * @author Phillip Webb + * @since 4.0.0 */ -class ForwardHeadersCustomizer implements JettyServerCustomizer { +public class ForwardHeadersCustomizer implements JettyServerCustomizer { @Override public void customize(Server server) { diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/GracefulShutdown.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/GracefulShutdown.java similarity index 98% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/GracefulShutdown.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/GracefulShutdown.java index 3d8582a82f..7c0ad72c01 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/GracefulShutdown.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/GracefulShutdown.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.jetty; +package org.springframework.boot.web.server.jetty; import java.lang.reflect.Method; import java.util.concurrent.CompletableFuture; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyHandlerWrappers.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/JettyHandlerWrappers.java similarity index 95% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyHandlerWrappers.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/JettyHandlerWrappers.java index bb61f81c6b..3b7522117a 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyHandlerWrappers.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/JettyHandlerWrappers.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.jetty; +package org.springframework.boot.web.server.jetty; import org.eclipse.jetty.http.HttpFields.Mutable; import org.eclipse.jetty.http.HttpMethod; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyServerCustomizer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/JettyServerCustomizer.java similarity index 81% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyServerCustomizer.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/JettyServerCustomizer.java index 7aeb364e33..89065f021e 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyServerCustomizer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/JettyServerCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,15 +14,17 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.jetty; +package org.springframework.boot.web.server.jetty; import org.eclipse.jetty.server.Server; +import org.springframework.boot.web.server.servlet.jetty.JettyServletWebServerFactory; + /** * Callback interface that can be used to customize a Jetty {@link Server}. * * @author Dave Syer - * @since 2.0.0 + * @since 4.0.0 * @see JettyServletWebServerFactory */ @FunctionalInterface diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyWebServer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/JettyWebServer.java similarity index 85% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyWebServer.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/JettyWebServer.java index 5fd713374a..70e3aaf3f4 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyWebServer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/JettyWebServer.java @@ -14,15 +14,18 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.jetty; +package org.springframework.boot.web.server.jetty; import java.io.IOException; +import java.util.Collection; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.eclipse.jetty.ee10.servlet.ServletContextHandler; +import org.eclipse.jetty.ee10.servlet.ServletHolder; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.NetworkConnector; @@ -35,7 +38,8 @@ import org.springframework.boot.web.server.GracefulShutdownResult; import org.springframework.boot.web.server.PortInUseException; import org.springframework.boot.web.server.WebServer; import org.springframework.boot.web.server.WebServerException; -import org.springframework.boot.web.server.WebServerFactory; +import org.springframework.boot.web.server.reactive.jetty.JettyReactiveWebServerFactory; +import org.springframework.http.server.reactive.ServletHttpHandlerAdapter; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -48,7 +52,7 @@ import org.springframework.util.StringUtils; * @author Eddú Meléndez * @author Brian Clozel * @author Kristine Jetzke - * @since 2.0.0 + * @since 4.0.0 * @see JettyReactiveWebServerFactory */ public class JettyWebServer implements WebServer { @@ -150,9 +154,7 @@ public class JettyWebServer implements WebServer { } try { this.server.start(); - for (Handler handler : this.server.getHandlers()) { - handleDeferredInitialize(handler); - } + handleDeferredInitialize(this.server); Connector[] connectors = this.server.getConnectors(); for (Connector connector : connectors) { try { @@ -208,15 +210,16 @@ public class JettyWebServer implements WebServer { } private String getContextPath() { - if (JettyReactiveWebServerFactory.class.equals(this.server.getAttribute(WebServerFactory.class.getName()))) { - return null; - } - return this.server.getHandlers() + List imperativeContextHandlers = this.server.getHandlers() .stream() .map(this::findContextHandler) .filter(Objects::nonNull) - .map(ContextHandler::getContextPath) - .collect(Collectors.joining(" ")); + .filter(this::isImperative) + .toList(); + if (imperativeContextHandlers.isEmpty()) { + return null; + } + return imperativeContextHandlers.stream().map(ContextHandler::getContextPath).collect(Collectors.joining(" ")); } private ContextHandler findContextHandler(Handler handler) { @@ -229,22 +232,26 @@ public class JettyWebServer implements WebServer { return null; } - private void handleDeferredInitialize(List handlers) throws Exception { - for (Handler handler : handlers) { - handleDeferredInitialize(handler); + private boolean isImperative(ContextHandler contextHandler) { + if (contextHandler instanceof ServletContextHandler servletContextHandler) { + Collection servletHolders = servletContextHandler.getServletHandler() + .getBeans(ServletHolder.class); + for (ServletHolder servletHolder : servletHolders) { + if (ServletHttpHandlerAdapter.class.getName().equals(servletHolder.getClassName())) { + return false; + } + } } + return true; } - private void handleDeferredInitialize(Handler handler) throws Exception { - if (handler instanceof JettyEmbeddedWebAppContext jettyEmbeddedWebAppContext) { - jettyEmbeddedWebAppContext.deferredInitialize(); - } - else if (handler instanceof Handler.Wrapper handlerWrapper) { - handleDeferredInitialize(handlerWrapper.getHandler()); - } - else if (handler instanceof Handler.Collection handlerCollection) { - handleDeferredInitialize(handlerCollection.getHandlers()); - } + /** + * Performs any necessary handling of deferred initialization. + * @param server the server that has been started + * @throws Exception if a failure occurs during the deferred initialization + */ + protected void handleDeferredInitialize(Server server) throws Exception { + } @Override diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyReactiveWebServerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/JettyWebServerFactory.java similarity index 50% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyReactiveWebServerFactory.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/JettyWebServerFactory.java index 7639bed7f1..377b4ac186 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyReactiveWebServerFactory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/JettyWebServerFactory.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.jetty; +package org.springframework.boot.web.server.jetty; import java.net.InetSocketAddress; import java.util.ArrayList; @@ -23,84 +23,59 @@ import java.util.Collection; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.Executor; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.eclipse.jetty.ee10.servlet.ServletContextHandler; -import org.eclipse.jetty.ee10.servlet.ServletHolder; +import org.eclipse.jetty.ee10.webapp.Configuration; +import org.eclipse.jetty.ee10.webapp.WebAppContext; import org.eclipse.jetty.http2.server.HTTP2CServerConnectionFactory; +import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.server.AbstractConnector; import org.eclipse.jetty.server.ConnectionFactory; -import org.eclipse.jetty.server.ConnectionLimit; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.server.handler.StatisticsHandler; +import org.eclipse.jetty.util.thread.Scheduler; import org.eclipse.jetty.util.thread.ThreadPool; -import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactory; -import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; -import org.springframework.boot.web.server.Shutdown; -import org.springframework.boot.web.server.Ssl; -import org.springframework.boot.web.server.WebServer; -import org.springframework.http.client.reactive.JettyResourceFactory; -import org.springframework.http.server.reactive.HttpHandler; -import org.springframework.http.server.reactive.ServletHttpHandlerAdapter; +import org.springframework.boot.web.server.AbstractConfigurableWebServerFactory; import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** - * {@link ReactiveWebServerFactory} that can be used to create {@link JettyWebServer}s. + * Base class for factories that produce a {@link JettyWebServer}. * - * @author Brian Clozel - * @author Moritz Halbritter - * @since 2.0.0 + * @author Andy Wilkinson + * @since 4.0.0 */ -public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFactory +public class JettyWebServerFactory extends AbstractConfigurableWebServerFactory implements ConfigurableJettyWebServerFactory { - private static final Log logger = LogFactory.getLog(JettyReactiveWebServerFactory.class); - - /** - * The number of acceptor threads to use. - */ private int acceptors = -1; - /** - * The number of selector threads to use. - */ + private ThreadPool threadPool; + private int selectors = -1; + private List configurations = new ArrayList<>(); + private boolean useForwardHeaders; private Set jettyServerCustomizers = new LinkedHashSet<>(); - private JettyResourceFactory resourceFactory; - - private ThreadPool threadPool; - private int maxConnections = -1; - /** - * Create a new {@link JettyServletWebServerFactory} instance. - */ - public JettyReactiveWebServerFactory() { + public JettyWebServerFactory() { + } - /** - * Create a new {@link JettyServletWebServerFactory} that listens for requests using - * the specified port. - * @param port the port to listen on - */ - public JettyReactiveWebServerFactory(int port) { + public JettyWebServerFactory(int port) { super(port); } - @Override - public void setUseForwardHeaders(boolean useForwardHeaders) { - this.useForwardHeaders = useForwardHeaders; + public int getAcceptors() { + return this.acceptors; } @Override @@ -108,17 +83,17 @@ public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFact this.acceptors = acceptors; } - @Override - public WebServer getWebServer(HttpHandler httpHandler) { - ServletHttpHandlerAdapter servlet = new ServletHttpHandlerAdapter(httpHandler); - Server server = createJettyServer(servlet); - return new JettyWebServer(server, getPort() >= 0); + public int getSelectors() { + return this.selectors; } @Override - public void addServerCustomizers(JettyServerCustomizer... customizers) { - Assert.notNull(customizers, "'customizers' must not be null"); - this.jettyServerCustomizers.addAll(Arrays.asList(customizers)); + public void setSelectors(int selectors) { + this.selectors = selectors; + } + + public int getMaxConnections() { + return this.maxConnections; } @Override @@ -126,6 +101,15 @@ public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFact this.maxConnections = maxConnections; } + /** + * Returns a mutable collection of Jetty {@link JettyServerCustomizer}s that will be + * applied to the {@link Server} before it is created. + * @return the {@link JettyServerCustomizer}s + */ + public Collection getServerCustomizers() { + return this.jettyServerCustomizers; + } + /** * Sets {@link JettyServerCustomizer}s that will be applied to the {@link Server} * before it is started. Calling this method will replace any existing customizers. @@ -136,13 +120,40 @@ public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFact this.jettyServerCustomizers = new LinkedHashSet<>(customizers); } + @Override + public void addServerCustomizers(JettyServerCustomizer... customizers) { + Assert.notNull(customizers, "'customizers' must not be null"); + this.jettyServerCustomizers.addAll(Arrays.asList(customizers)); + } + /** - * Returns a mutable collection of Jetty {@link JettyServerCustomizer}s that will be - * applied to the {@link Server} before it is created. - * @return the Jetty customizers + * Returns a mutable collection of Jetty {@link Configuration}s that will be applied + * to the {@link WebAppContext} before the server is created. + * @return the Jetty {@link Configuration}s */ - public Collection getServerCustomizers() { - return this.jettyServerCustomizers; + public Collection getConfigurations() { + return this.configurations; + } + + /** + * Sets Jetty {@link Configuration}s that will be applied to the {@link WebAppContext} + * before the server is created. Calling this method will replace any existing + * configurations. + * @param configurations the Jetty configurations to apply + */ + public void setConfigurations(Collection configurations) { + Assert.notNull(configurations, "'configurations' must not be null"); + this.configurations = new ArrayList<>(configurations); + } + + /** + * Add {@link Configuration}s that will be applied to the {@link WebAppContext} before + * the server is started. + * @param configurations the configurations to add + */ + public void addConfigurations(Configuration... configurations) { + Assert.notNull(configurations, "'configurations' must not be null"); + this.configurations.addAll(Arrays.asList(configurations)); } /** @@ -158,58 +169,21 @@ public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFact this.threadPool = threadPool; } + public boolean isUseForwardHeaders() { + return this.useForwardHeaders; + } + @Override - public void setSelectors(int selectors) { - this.selectors = selectors; + public void setUseForwardHeaders(boolean useForwardHeaders) { + this.useForwardHeaders = useForwardHeaders; } - /** - * Set the {@link JettyResourceFactory} to get the shared resources from. - * @param resourceFactory the server resources - * @since 2.1.0 - */ - public void setResourceFactory(JettyResourceFactory resourceFactory) { - this.resourceFactory = resourceFactory; + protected AbstractConnector createConnector(InetSocketAddress address, Server server) { + return this.createConnector(address, server, null, null, null); } - protected JettyResourceFactory getResourceFactory() { - return this.resourceFactory; - } - - protected Server createJettyServer(ServletHttpHandlerAdapter servlet) { - int port = Math.max(getPort(), 0); - InetSocketAddress address = new InetSocketAddress(getAddress(), port); - Server server = new Server(getThreadPool()); - server.addConnector(createConnector(address, server)); - server.setStopTimeout(0); - ServletHolder servletHolder = new ServletHolder(servlet); - servletHolder.setAsyncSupported(true); - ServletContextHandler contextHandler = new ServletContextHandler("/", false, false); - contextHandler.addServlet(servletHolder, "/"); - server.setHandler(addHandlerWrappers(contextHandler)); - JettyReactiveWebServerFactory.logger.info("Server initialized with port: " + port); - if (this.maxConnections > -1) { - server.addBean(new ConnectionLimit(this.maxConnections, server)); - } - if (Ssl.isEnabled(getSsl())) { - customizeSsl(server, address); - } - for (JettyServerCustomizer customizer : getServerCustomizers()) { - customizer.customize(server); - } - if (this.useForwardHeaders) { - new ForwardHeadersCustomizer().customize(server); - } - if (getShutdown() == Shutdown.GRACEFUL) { - StatisticsHandler statisticsHandler = new StatisticsHandler(); - statisticsHandler.setHandler(server.getHandler()); - server.setHandler(statisticsHandler); - } - server.setAttribute(org.springframework.boot.web.server.WebServerFactory.class.getName(), getClass()); - return server; - } - - private AbstractConnector createConnector(InetSocketAddress address, Server server) { + protected AbstractConnector createConnector(InetSocketAddress address, Server server, Executor executor, + Scheduler scheduler, ByteBufferPool pool) { HttpConfiguration httpConfiguration = new HttpConfiguration(); httpConfiguration.setSendServerVersion(false); List connectionFactories = new ArrayList<>(); @@ -217,23 +191,20 @@ public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFact if (getHttp2() != null && getHttp2().isEnabled()) { connectionFactories.add(new HTTP2CServerConnectionFactory(httpConfiguration)); } - JettyResourceFactory resourceFactory = getResourceFactory(); - ServerConnector connector; - if (resourceFactory != null) { - connector = new ServerConnector(server, resourceFactory.getExecutor(), resourceFactory.getScheduler(), - resourceFactory.getByteBufferPool(), this.acceptors, this.selectors, - connectionFactories.toArray(new ConnectionFactory[0])); - } - else { - connector = new ServerConnector(server, this.acceptors, this.selectors, - connectionFactories.toArray(new ConnectionFactory[0])); - } + ServerConnector connector = new ServerConnector(server, executor, scheduler, pool, this.getAcceptors(), + this.getSelectors(), connectionFactories.toArray(new ConnectionFactory[0])); + connector.setHost(address.getHostString()); connector.setPort(address.getPort()); return connector; } - private Handler addHandlerWrappers(Handler handler) { + protected void customizeSsl(Server server, InetSocketAddress address) { + Assert.state(getSsl().getServerNameBundles().isEmpty(), "Server name SSL bundles are not supported with Jetty"); + new SslServerCustomizer(getHttp2(), address, getSsl().getClientAuth(), getSslBundle()).customize(server); + } + + protected Handler addHandlerWrappers(Handler handler) { if (getCompression() != null && getCompression().getEnabled()) { handler = applyWrapper(handler, JettyHandlerWrappers.createGzipHandlerWrapper(getCompression())); } @@ -243,14 +214,9 @@ public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFact return handler; } - private Handler applyWrapper(Handler handler, Handler.Wrapper wrapper) { + protected Handler applyWrapper(Handler handler, Handler.Wrapper wrapper) { wrapper.setHandler(handler); return wrapper; } - private void customizeSsl(Server server, InetSocketAddress address) { - Assert.state(getSsl().getServerNameBundles().isEmpty(), "Server name SSL bundles are not supported with Jetty"); - new SslServerCustomizer(getHttp2(), address, getSsl().getClientAuth(), getSslBundle()).customize(server); - } - } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/SslServerCustomizer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/SslServerCustomizer.java similarity index 98% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/SslServerCustomizer.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/SslServerCustomizer.java index f215f9d441..3095276740 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/SslServerCustomizer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/SslServerCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.jetty; +package org.springframework.boot.web.server.jetty; import java.net.InetSocketAddress; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/package-info.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/package-info.java similarity index 63% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/package-info.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/package-info.java index b5a8dedcf7..372a937c5f 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/package-info.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/jetty/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,9 +15,9 @@ */ /** - * Embedded reactive and servlet web server implementations backed by Undertow. + * Reactive and servlet web server implementations backed by Jetty. * - * @see org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory - * @see org.springframework.boot.web.embedded.undertow.UndertowReactiveWebServerFactory + * @see org.springframework.boot.web.server.servlet.jetty.JettyServletWebServerFactory + * @see org.springframework.boot.web.server.reactive.jetty.JettyReactiveWebServerFactory */ -package org.springframework.boot.web.embedded.undertow; +package org.springframework.boot.web.server.jetty; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/server/AbstractReactiveWebServerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/AbstractReactiveWebServerFactory.java similarity index 89% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/server/AbstractReactiveWebServerFactory.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/AbstractReactiveWebServerFactory.java index 227261938b..9b2d3e6ce1 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/server/AbstractReactiveWebServerFactory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/AbstractReactiveWebServerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.reactive.server; +package org.springframework.boot.web.server.reactive; import org.springframework.boot.web.server.AbstractConfigurableWebServerFactory; @@ -22,7 +22,7 @@ import org.springframework.boot.web.server.AbstractConfigurableWebServerFactory; * Abstract base class for {@link ReactiveWebServerFactory} implementations. * * @author Brian Clozel - * @since 2.0.0 + * @since 4.0.0 */ public abstract class AbstractReactiveWebServerFactory extends AbstractConfigurableWebServerFactory implements ConfigurableReactiveWebServerFactory { diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/server/ConfigurableReactiveWebServerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/ConfigurableReactiveWebServerFactory.java similarity index 87% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/server/ConfigurableReactiveWebServerFactory.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/ConfigurableReactiveWebServerFactory.java index 698f8d145c..94334ec5a1 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/server/ConfigurableReactiveWebServerFactory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/ConfigurableReactiveWebServerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.reactive.server; +package org.springframework.boot.web.server.reactive; import org.springframework.boot.web.server.ConfigurableWebServerFactory; @@ -22,7 +22,7 @@ import org.springframework.boot.web.server.ConfigurableWebServerFactory; * Configurable {@link ReactiveWebServerFactory}. * * @author Brian Clozel - * @since 2.0.0 + * @since 4.0.0 */ public interface ConfigurableReactiveWebServerFactory extends ConfigurableWebServerFactory, ReactiveWebServerFactory { diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/server/ReactiveWebServerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/ReactiveWebServerFactory.java similarity index 92% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/server/ReactiveWebServerFactory.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/ReactiveWebServerFactory.java index 101137d064..8e7f209532 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/server/ReactiveWebServerFactory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/ReactiveWebServerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.reactive.server; +package org.springframework.boot.web.server.reactive; import org.springframework.boot.web.server.WebServer; import org.springframework.boot.web.server.WebServerFactory; @@ -24,7 +24,7 @@ import org.springframework.http.server.reactive.HttpHandler; * Factory interface that can be used to create a reactive {@link WebServer}. * * @author Brian Clozel - * @since 2.0.0 + * @since 4.0.0 * @see WebServer */ @FunctionalInterface diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/jetty/JettyReactiveWebServerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/jetty/JettyReactiveWebServerFactory.java new file mode 100644 index 0000000000..7fa57291c4 --- /dev/null +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/jetty/JettyReactiveWebServerFactory.java @@ -0,0 +1,130 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.web.server.reactive.jetty; + +import java.net.InetSocketAddress; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.eclipse.jetty.ee10.servlet.ServletContextHandler; +import org.eclipse.jetty.ee10.servlet.ServletHolder; +import org.eclipse.jetty.server.ConnectionLimit; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.handler.StatisticsHandler; + +import org.springframework.boot.web.server.Shutdown; +import org.springframework.boot.web.server.Ssl; +import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.jetty.ConfigurableJettyWebServerFactory; +import org.springframework.boot.web.server.jetty.ForwardHeadersCustomizer; +import org.springframework.boot.web.server.jetty.JettyServerCustomizer; +import org.springframework.boot.web.server.jetty.JettyWebServer; +import org.springframework.boot.web.server.jetty.JettyWebServerFactory; +import org.springframework.boot.web.server.reactive.ConfigurableReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.ReactiveWebServerFactory; +import org.springframework.boot.web.server.servlet.jetty.JettyServletWebServerFactory; +import org.springframework.http.client.reactive.JettyResourceFactory; +import org.springframework.http.server.reactive.HttpHandler; +import org.springframework.http.server.reactive.ServletHttpHandlerAdapter; + +/** + * {@link ReactiveWebServerFactory} that can be used to create {@link JettyWebServer}s. + * + * @author Brian Clozel + * @author Moritz Halbritter + * @since 4.0.0 + */ +public class JettyReactiveWebServerFactory extends JettyWebServerFactory + implements ConfigurableJettyWebServerFactory, ConfigurableReactiveWebServerFactory { + + private static final Log logger = LogFactory.getLog(JettyReactiveWebServerFactory.class); + + private JettyResourceFactory resourceFactory; + + /** + * Create a new {@link JettyServletWebServerFactory} instance. + */ + public JettyReactiveWebServerFactory() { + } + + /** + * Create a new {@link JettyServletWebServerFactory} that listens for requests using + * the specified port. + * @param port the port to listen on + */ + public JettyReactiveWebServerFactory(int port) { + super(port); + } + + @Override + public WebServer getWebServer(HttpHandler httpHandler) { + ServletHttpHandlerAdapter servlet = new ServletHttpHandlerAdapter(httpHandler); + Server server = createJettyServer(servlet); + return new JettyWebServer(server, getPort() >= 0); + } + + /** + * Set the {@link JettyResourceFactory} to get the shared resources from. + * @param resourceFactory the server resources + */ + public void setResourceFactory(JettyResourceFactory resourceFactory) { + this.resourceFactory = resourceFactory; + } + + protected JettyResourceFactory getResourceFactory() { + return this.resourceFactory; + } + + protected Server createJettyServer(ServletHttpHandlerAdapter servlet) { + int port = Math.max(getPort(), 0); + InetSocketAddress address = new InetSocketAddress(getAddress(), port); + Server server = new Server(getThreadPool()); + if (this.resourceFactory == null) { + server.addConnector(createConnector(address, server)); + } + else { + server.addConnector(createConnector(address, server, this.resourceFactory.getExecutor(), + this.resourceFactory.getScheduler(), this.resourceFactory.getByteBufferPool())); + } + server.setStopTimeout(0); + ServletHolder servletHolder = new ServletHolder(servlet); + servletHolder.setAsyncSupported(true); + ServletContextHandler contextHandler = new ServletContextHandler("/", false, false); + contextHandler.addServlet(servletHolder, "/"); + server.setHandler(addHandlerWrappers(contextHandler)); + logger.info("Server initialized with port: " + port); + if (this.getMaxConnections() > -1) { + server.addBean(new ConnectionLimit(this.getMaxConnections(), server)); + } + if (Ssl.isEnabled(getSsl())) { + customizeSsl(server, address); + } + for (JettyServerCustomizer customizer : getServerCustomizers()) { + customizer.customize(server); + } + if (this.isUseForwardHeaders()) { + new ForwardHeadersCustomizer().customize(server); + } + if (getShutdown() == Shutdown.GRACEFUL) { + StatisticsHandler statisticsHandler = new StatisticsHandler(); + statisticsHandler.setHandler(server.getHandler()); + server.setHandler(statisticsHandler); + } + return server; + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/package-info.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/jetty/package-info.java similarity index 76% rename from spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/package-info.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/jetty/package-info.java index ead77417cb..478571b1d4 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/package-info.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/jetty/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ */ /** - * Configuration for embedded reactive and servlet web servers. + * Reactive web server implementation backed by Jetty. + * */ -package org.springframework.boot.autoconfigure.web.embedded; +package org.springframework.boot.web.server.reactive.jetty; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/CompressionCustomizer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/netty/CompressionCustomizer.java similarity index 96% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/CompressionCustomizer.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/netty/CompressionCustomizer.java index 57828601fa..c12978d98b 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/CompressionCustomizer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/netty/CompressionCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.netty; +package org.springframework.boot.web.server.reactive.netty; import java.util.Arrays; import java.util.List; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/GracefulShutdown.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/netty/GracefulShutdown.java similarity index 95% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/GracefulShutdown.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/netty/GracefulShutdown.java index a67158e163..8d3c0d96a3 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/GracefulShutdown.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/netty/GracefulShutdown.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.netty; +package org.springframework.boot.web.server.reactive.netty; import java.time.Duration; import java.util.function.Supplier; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/NettyReactiveWebServerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/netty/NettyReactiveWebServerFactory.java similarity index 96% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/NettyReactiveWebServerFactory.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/netty/NettyReactiveWebServerFactory.java index b7503fddcc..f848c6887a 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/NettyReactiveWebServerFactory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/netty/NettyReactiveWebServerFactory.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.netty; +package org.springframework.boot.web.server.reactive.netty; import java.net.InetSocketAddress; import java.time.Duration; @@ -28,11 +28,11 @@ import java.util.Set; import reactor.netty.http.HttpProtocol; import reactor.netty.http.server.HttpServer; -import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactory; -import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; import org.springframework.boot.web.server.Shutdown; import org.springframework.boot.web.server.Ssl; import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.reactive.AbstractReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.ReactiveWebServerFactory; import org.springframework.http.client.ReactorResourceFactory; import org.springframework.http.server.reactive.HttpHandler; import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter; @@ -45,7 +45,7 @@ import org.springframework.util.StringUtils; * @author Brian Clozel * @author Moritz Halbritter * @author Scott Frederick - * @since 2.0.0 + * @since 4.0.0 */ public class NettyReactiveWebServerFactory extends AbstractReactiveWebServerFactory { @@ -134,7 +134,7 @@ public class NettyReactiveWebServerFactory extends AbstractReactiveWebServerFact /** * Set if x-forward-* headers should be processed. * @param useForwardHeaders if x-forward headers should be used - * @since 2.1.0 + * @since 4.0.0 */ public void setUseForwardHeaders(boolean useForwardHeaders) { this.useForwardHeaders = useForwardHeaders; @@ -143,7 +143,7 @@ public class NettyReactiveWebServerFactory extends AbstractReactiveWebServerFact /** * Set the {@link ReactorResourceFactory} to get the shared resources from. * @param resourceFactory the server resources - * @since 2.1.0 + * @since 4.0.0 */ public void setResourceFactory(ReactorResourceFactory resourceFactory) { this.resourceFactory = resourceFactory; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/NettyRouteProvider.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/netty/NettyRouteProvider.java similarity index 87% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/NettyRouteProvider.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/netty/NettyRouteProvider.java index 0152ff41d9..4c09b8a3db 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/NettyRouteProvider.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/netty/NettyRouteProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.netty; +package org.springframework.boot.web.server.reactive.netty; import java.util.function.Function; @@ -24,7 +24,7 @@ import reactor.netty.http.server.HttpServerRoutes; * Function that can add new routes to an {@link HttpServerRoutes} instance. * * @author Brian Clozel - * @since 2.2.0 + * @since 4.0.0 * @see NettyReactiveWebServerFactory */ @FunctionalInterface diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/NettyServerCustomizer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/netty/NettyServerCustomizer.java similarity index 87% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/NettyServerCustomizer.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/netty/NettyServerCustomizer.java index ddb54a451b..742e7625a7 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/NettyServerCustomizer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/netty/NettyServerCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.netty; +package org.springframework.boot.web.server.reactive.netty; import java.util.function.Function; @@ -24,7 +24,7 @@ import reactor.netty.http.server.HttpServer; * Mapping function that can be used to customize a Reactor Netty server instance. * * @author Brian Clozel - * @since 2.1.0 + * @since 4.0.0 * @see NettyReactiveWebServerFactory */ @FunctionalInterface diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/NettyWebServer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/netty/NettyWebServer.java similarity index 98% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/NettyWebServer.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/netty/NettyWebServer.java index 414aa2d87c..682784cdbe 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/NettyWebServer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/netty/NettyWebServer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.netty; +package org.springframework.boot.web.server.reactive.netty; import java.time.Duration; import java.util.Collections; @@ -55,7 +55,7 @@ import org.springframework.util.Assert; * @author Brian Clozel * @author Madhura Bhave * @author Andy Wilkinson - * @since 2.0.0 + * @since 4.0.0 */ public class NettyWebServer implements WebServer { @@ -90,7 +90,7 @@ public class NettyWebServer implements WebServer { * @param shutdown the shutdown, may be {@code null} * @param resourceFactory the factory for the server's {@link LoopResources loop * resources}, may be {@code null} - * @since 3.2.0 + * @since 4.0.0 */ public NettyWebServer(HttpServer httpServer, ReactorHttpHandlerAdapter handlerAdapter, Duration lifecycleTimeout, Shutdown shutdown, ReactorResourceFactory resourceFactory) { diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/SslServerCustomizer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/netty/SslServerCustomizer.java similarity index 96% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/SslServerCustomizer.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/netty/SslServerCustomizer.java index 021610461a..42924e2eab 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/SslServerCustomizer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/netty/SslServerCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.netty; +package org.springframework.boot.web.server.reactive.netty; import java.util.HashMap; import java.util.Map; @@ -46,7 +46,7 @@ import org.springframework.boot.web.server.Ssl; * @author Scott Frederick * @author Moritz Halbritter * @author Phillip Webb - * @since 2.0.0 + * @since 4.0.0 */ public class SslServerCustomizer implements NettyServerCustomizer { @@ -107,7 +107,7 @@ public class SslServerCustomizer implements NettyServerCustomizer { * Create an {@link AbstractProtocolSslContextSpec} for a given {@link SslBundle}. * @param sslBundle the {@link SslBundle} to use * @return an {@link AbstractProtocolSslContextSpec} instance - * @since 3.2.0 + * @since 4.0.0 */ protected final AbstractProtocolSslContextSpec createSslContextSpec(SslBundle sslBundle) { AbstractProtocolSslContextSpec sslContextSpec = (this.http2 != null && this.http2.isEnabled()) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/reactive/package-info.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/netty/package-info.java similarity index 75% rename from spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/reactive/package-info.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/netty/package-info.java index f3fd05da20..96f6635163 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/reactive/package-info.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/netty/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ */ /** - * Auto-configuration for WebSocket support in reactive web servers. + * Reactive web server implementation backed by Netty. + * */ -package org.springframework.boot.autoconfigure.websocket.reactive; +package org.springframework.boot.web.server.reactive.netty; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/server/package-info.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/package-info.java similarity index 84% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/server/package-info.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/package-info.java index 5ee2267484..28aafd097a 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/server/package-info.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,4 +17,4 @@ /** * Reactive web server abstractions. */ -package org.springframework.boot.web.reactive.server; +package org.springframework.boot.web.server.reactive; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/tomcat/TomcatReactiveWebServerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/tomcat/TomcatReactiveWebServerFactory.java new file mode 100644 index 0000000000..2fde4918e3 --- /dev/null +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/tomcat/TomcatReactiveWebServerFactory.java @@ -0,0 +1,134 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.web.server.reactive.tomcat; + +import java.io.File; + +import org.apache.catalina.Context; +import org.apache.catalina.Host; +import org.apache.catalina.WebResourceRoot; +import org.apache.catalina.loader.WebappLoader; +import org.apache.catalina.startup.Tomcat; +import org.apache.catalina.webresources.StandardRoot; +import org.apache.tomcat.util.scan.StandardJarScanFilter; + +import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.reactive.ConfigurableReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.ReactiveWebServerFactory; +import org.springframework.boot.web.server.tomcat.ConfigurableTomcatWebServerFactory; +import org.springframework.boot.web.server.tomcat.DisableReferenceClearingContextCustomizer; +import org.springframework.boot.web.server.tomcat.TomcatEmbeddedContext; +import org.springframework.boot.web.server.tomcat.TomcatEmbeddedWebappClassLoader; +import org.springframework.boot.web.server.tomcat.TomcatWebServer; +import org.springframework.boot.web.server.tomcat.TomcatWebServerFactory; +import org.springframework.http.server.reactive.HttpHandler; +import org.springframework.http.server.reactive.TomcatHttpHandlerAdapter; +import org.springframework.util.ClassUtils; + +/** + * {@link ReactiveWebServerFactory} that can be used to create a {@link TomcatWebServer}. + * + * @author Brian Clozel + * @author HaiTao Zhang + * @author Moritz Halbritter + * @author Scott Frederick + * @since 4.0.0 + */ +public class TomcatReactiveWebServerFactory extends TomcatWebServerFactory + implements ConfigurableTomcatWebServerFactory, ConfigurableReactiveWebServerFactory { + + /** + * Create a new {@link TomcatReactiveWebServerFactory} instance. + */ + public TomcatReactiveWebServerFactory() { + } + + /** + * Create a new {@link TomcatReactiveWebServerFactory} that listens for requests using + * the specified port. + * @param port the port to listen on + */ + public TomcatReactiveWebServerFactory(int port) { + super(port); + } + + @Override + public WebServer getWebServer(HttpHandler httpHandler) { + Tomcat tomcat = createTomcat(); + TomcatHttpHandlerAdapter servlet = new TomcatHttpHandlerAdapter(httpHandler); + prepareContext(tomcat.getHost(), servlet); + return getTomcatWebServer(tomcat); + } + + protected void prepareContext(Host host, TomcatHttpHandlerAdapter servlet) { + File docBase = createTempDir("tomcat-docbase"); + TomcatEmbeddedContext context = new TomcatEmbeddedContext(); + WebResourceRoot resourceRoot = new StandardRoot(context); + ignoringNoSuchMethodError(() -> resourceRoot.setReadOnly(true)); + context.setResources(resourceRoot); + context.setPath(""); + context.setDocBase(docBase.getAbsolutePath()); + context.addLifecycleListener(new Tomcat.FixContextListener()); + ClassLoader parentClassLoader = ClassUtils.getDefaultClassLoader(); + context.setParentClassLoader(parentClassLoader); + skipAllTldScanning(context); + WebappLoader loader = new WebappLoader(); + loader.setLoaderInstance(new TomcatEmbeddedWebappClassLoader(parentClassLoader)); + loader.setDelegate(true); + context.setLoader(loader); + Tomcat.addServlet(context, "httpHandlerServlet", servlet).setAsyncSupported(true); + context.addServletMappingDecoded("/", "httpHandlerServlet"); + host.addChild(context); + configureContext(context); + } + + private void ignoringNoSuchMethodError(Runnable method) { + try { + method.run(); + } + catch (NoSuchMethodError ex) { + } + } + + private void skipAllTldScanning(TomcatEmbeddedContext context) { + StandardJarScanFilter filter = new StandardJarScanFilter(); + filter.setTldSkip("*.jar"); + context.getJarScanner().setJarScanFilter(filter); + } + + /** + * Configure the Tomcat {@link Context}. + * @param context the Tomcat context + */ + protected void configureContext(Context context) { + this.getContextLifecycleListeners().forEach(context::addLifecycleListener); + new DisableReferenceClearingContextCustomizer().customize(context); + this.getContextCustomizers().forEach((customizer) -> customizer.customize(context)); + } + + /** + * Factory method called to create the {@link TomcatWebServer}. Subclasses can + * override this method to return a different {@link TomcatWebServer} or apply + * additional processing to the Tomcat server. + * @param tomcat the Tomcat server. + * @return a new {@link TomcatWebServer} instance + */ + protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) { + return new TomcatWebServer(tomcat, getPort() >= 0, getShutdown()); + } + +} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/tomcat/package-info.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/tomcat/package-info.java new file mode 100644 index 0000000000..dce179a946 --- /dev/null +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/tomcat/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Reactive web server implementation backed by Tomcat. + */ +package org.springframework.boot.web.server.reactive.tomcat; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/undertow/UndertowReactiveWebServerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/undertow/UndertowReactiveWebServerFactory.java new file mode 100644 index 0000000000..ff8ca05118 --- /dev/null +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/undertow/UndertowReactiveWebServerFactory.java @@ -0,0 +1,65 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.web.server.reactive.undertow; + +import java.util.List; + +import io.undertow.Undertow; + +import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.reactive.ConfigurableReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.ReactiveWebServerFactory; +import org.springframework.boot.web.server.undertow.ConfigurableUndertowWebServerFactory; +import org.springframework.boot.web.server.undertow.HttpHandlerFactory; +import org.springframework.boot.web.server.undertow.UndertowWebServer; +import org.springframework.boot.web.server.undertow.UndertowWebServerFactory; +import org.springframework.http.server.reactive.UndertowHttpHandlerAdapter; + +/** + * {@link ReactiveWebServerFactory} that can be used to create {@link UndertowWebServer}s. + * + * @author Brian Clozel + * @author Scott Frederick + * @since 4.0.0 + */ +public class UndertowReactiveWebServerFactory extends UndertowWebServerFactory + implements ConfigurableUndertowWebServerFactory, ConfigurableReactiveWebServerFactory { + + /** + * Create a new {@link UndertowReactiveWebServerFactory} instance. + */ + public UndertowReactiveWebServerFactory() { + } + + /** + * Create a new {@link UndertowReactiveWebServerFactory} that listens for requests + * using the specified port. + * @param port the port to listen on + */ + public UndertowReactiveWebServerFactory(int port) { + super(port); + } + + @Override + public WebServer getWebServer(org.springframework.http.server.reactive.HttpHandler httpHandler) { + Undertow.Builder builder = createBuilder(this, this::getSslBundle, this::getServerNameSslBundles); + List httpHandlerFactories = createHttpHandlerFactories(this, + (next) -> new UndertowHttpHandlerAdapter(httpHandler)); + return new UndertowWebServer(builder, httpHandlerFactories, getPort() >= 0); + } + +} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/undertow/package-info.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/undertow/package-info.java new file mode 100644 index 0000000000..4f040dbcb8 --- /dev/null +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/reactive/undertow/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Reactive web server implementation backed by Undertow. + */ +package org.springframework.boot.web.server.reactive.undertow; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/ConfigurableServletWebServerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/ConfigurableServletWebServerFactory.java similarity index 64% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/ConfigurableServletWebServerFactory.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/ConfigurableServletWebServerFactory.java index c4b442a45f..7af6ee8942 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/ConfigurableServletWebServerFactory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/ConfigurableServletWebServerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.servlet.server; +package org.springframework.boot.web.server.servlet; import java.io.File; import java.nio.charset.Charset; @@ -28,8 +28,6 @@ import org.springframework.boot.web.server.ConfigurableWebServerFactory; import org.springframework.boot.web.server.Cookie.SameSite; import org.springframework.boot.web.server.MimeMappings; import org.springframework.boot.web.server.WebServerFactoryCustomizer; -import org.springframework.boot.web.servlet.ServletContextInitializer; -import org.springframework.boot.web.servlet.WebListenerRegistry; /** * A configurable {@link ServletWebServerFactory}. @@ -39,62 +37,86 @@ import org.springframework.boot.web.servlet.WebListenerRegistry; * @author Stephane Nicoll * @author Eddú Meléndez * @author Brian Clozel - * @since 2.0.0 + * @since 4.0.0 * @see ServletWebServerFactory * @see WebServerFactoryCustomizer */ public interface ConfigurableServletWebServerFactory extends ConfigurableWebServerFactory, ServletWebServerFactory, WebListenerRegistry { + ServletWebServerSettings getSettings(); + /** * Sets the context path for the web server. The context should start with a "/" * character but not end with a "/" character. The default context path can be * specified using an empty string. - * @param contextPath the contextPath to set + * @param contextPath the context path to set */ - void setContextPath(String contextPath); + default void setContextPath(String contextPath) { + getSettings().setContextPath(ContextPath.of(contextPath)); + } + + /** + * Returns the context path for the servlet web server. + * @return the context path + */ + default String getContextPath() { + return getSettings().getContextPath().toString(); + } /** * Sets the display name of the application deployed in the web server. * @param displayName the displayName to set - * @since 1.3.0 + * @since 4.0.0 */ - void setDisplayName(String displayName); + default void setDisplayName(String displayName) { + getSettings().setDisplayName(displayName); + } /** * Sets the configuration that will be applied to the container's HTTP session * support. * @param session the session configuration */ - void setSession(Session session); + default void setSession(Session session) { + getSettings().setSession(session); + } /** * Set if the DefaultServlet should be registered. Defaults to {@code false} since * 2.4. * @param registerDefaultServlet if the default servlet should be registered */ - void setRegisterDefaultServlet(boolean registerDefaultServlet); + default void setRegisterDefaultServlet(boolean registerDefaultServlet) { + getSettings().setRegisterDefaultServlet(registerDefaultServlet); + } /** * Sets the mime-type mappings. * @param mimeMappings the mime type mappings (defaults to * {@link MimeMappings#DEFAULT}) */ - void setMimeMappings(MimeMappings mimeMappings); + default void setMimeMappings(MimeMappings mimeMappings) { + getSettings().setMimeMappings(mimeMappings); + } /** * Adds mime-type mappings. * @param mimeMappings the mime type mappings to add - * @since 3.3.0 + * @since 4.0.0 */ - void addMimeMappings(MimeMappings mimeMappings); + default void addMimeMappings(MimeMappings mimeMappings) { + getSettings().addMimeMappings(mimeMappings); + } /** * Sets the document root directory which will be used by the web context to serve * static files. * @param documentRoot the document root or {@code null} if not required */ - void setDocumentRoot(File documentRoot); + default void setDocumentRoot(File documentRoot) { + getSettings().setDocumentRoot(documentRoot); + } /** * Sets {@link ServletContextInitializer} that should be applied in addition to @@ -103,7 +125,9 @@ public interface ConfigurableServletWebServerFactory * @param initializers the initializers to set * @see #addInitializers */ - void setInitializers(List initializers); + default void setInitializers(List initializers) { + getSettings().setInitializers(initializers); + } /** * Add {@link ServletContextInitializer}s to those that should be applied in addition @@ -112,26 +136,34 @@ public interface ConfigurableServletWebServerFactory * @param initializers the initializers to add * @see #setInitializers */ - void addInitializers(ServletContextInitializer... initializers); + default void addInitializers(ServletContextInitializer... initializers) { + getSettings().addInitializers(initializers); + } /** * Sets the configuration that will be applied to the server's JSP servlet. * @param jsp the JSP servlet configuration */ - void setJsp(Jsp jsp); + default void setJsp(Jsp jsp) { + getSettings().setJsp(jsp); + } /** * Sets the Locale to Charset mappings. * @param localeCharsetMappings the Locale to Charset mappings */ - void setLocaleCharsetMappings(Map localeCharsetMappings); + default void setLocaleCharsetMappings(Map localeCharsetMappings) { + getSettings().setLocaleCharsetMappings(localeCharsetMappings); + } /** * Sets the init parameters that are applied to the container's * {@link ServletContext}. * @param initParameters the init parameters */ - void setInitParameters(Map initParameters); + default void setInitParameters(Map initParameters) { + getSettings().setInitParameters(initParameters); + } /** * Sets {@link CookieSameSiteSupplier CookieSameSiteSuppliers} that should be used to @@ -140,7 +172,9 @@ public interface ConfigurableServletWebServerFactory * @param cookieSameSiteSuppliers the suppliers to add * @see #addCookieSameSiteSuppliers */ - void setCookieSameSiteSuppliers(List cookieSameSiteSuppliers); + default void setCookieSameSiteSuppliers(List cookieSameSiteSuppliers) { + getSettings().setCookieSameSiteSuppliers(cookieSameSiteSuppliers); + } /** * Add {@link CookieSameSiteSupplier CookieSameSiteSuppliers} to those that should be @@ -148,6 +182,13 @@ public interface ConfigurableServletWebServerFactory * @param cookieSameSiteSuppliers the suppliers to add * @see #setCookieSameSiteSuppliers */ - void addCookieSameSiteSuppliers(CookieSameSiteSupplier... cookieSameSiteSuppliers); + default void addCookieSameSiteSuppliers(CookieSameSiteSupplier... cookieSameSiteSuppliers) { + getSettings().addCookieSameSiteSuppliers(cookieSameSiteSuppliers); + } + + @Override + default void addWebListeners(String... webListenerClassNames) { + getSettings().addWebListenerClassNames(webListenerClassNames); + } } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/ContextPath.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/ContextPath.java new file mode 100644 index 0000000000..1426fb5d8b --- /dev/null +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/ContextPath.java @@ -0,0 +1,58 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.web.server.servlet; + +import org.springframework.util.Assert; + +/** + * The context path of a servlet web server. + * + * @author Andy Wilkinson + * @since 4.0.0 + */ +public final class ContextPath { + + /** + * The default context path. + */ + public static final ContextPath DEFAULT = ContextPath.of(""); + + private final String path; + + private ContextPath(String path) { + this.path = path; + } + + public static ContextPath of(String contextPath) { + Assert.notNull(contextPath, "'contextPath' must not be null"); + if (!contextPath.isEmpty()) { + if ("/".equals(contextPath)) { + throw new IllegalArgumentException("Root context path must be specified using an empty string"); + } + if (!contextPath.startsWith("/") || contextPath.endsWith("/")) { + throw new IllegalArgumentException("Context path must start with '/' and not end with '/'"); + } + } + return new ContextPath(contextPath); + } + + @Override + public String toString() { + return this.path; + } + +} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/CookieSameSiteSupplier.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/CookieSameSiteSupplier.java similarity index 98% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/CookieSameSiteSupplier.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/CookieSameSiteSupplier.java index c1c7ad16d4..2dc3ebdaab 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/CookieSameSiteSupplier.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/CookieSameSiteSupplier.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.servlet.server; +package org.springframework.boot.web.server.servlet; import java.util.function.Predicate; import java.util.function.Supplier; @@ -37,7 +37,7 @@ import org.springframework.util.ObjectUtils; * * * @author Phillip Webb - * @since 2.6.0 + * @since 4.0.0 * @see ConfigurableServletWebServerFactory#addCookieSameSiteSuppliers(CookieSameSiteSupplier...) */ @FunctionalInterface diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/DocumentRoot.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/DocumentRoot.java similarity index 93% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/DocumentRoot.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/DocumentRoot.java index f35f77fdb7..58f8a23f20 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/DocumentRoot.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/DocumentRoot.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.servlet.server; +package org.springframework.boot.web.server.servlet; import java.io.File; import java.net.JarURLConnection; @@ -30,9 +30,9 @@ import org.apache.commons.logging.Log; * Manages a {@link ServletWebServerFactory} document root. * * @author Phillip Webb - * @see AbstractServletWebServerFactory + * @since 4.0.0 */ -class DocumentRoot { +public class DocumentRoot { private static final String[] COMMON_DOC_ROOTS = { "src/main/webapp", "public", "static" }; @@ -40,7 +40,7 @@ class DocumentRoot { private File directory; - DocumentRoot(Log logger) { + public DocumentRoot(Log logger) { this.logger = logger; } @@ -48,7 +48,7 @@ class DocumentRoot { return this.directory; } - void setDirectory(File directory) { + public void setDirectory(File directory) { this.directory = directory; } @@ -57,7 +57,7 @@ class DocumentRoot { * warning and returning {@code null} otherwise. * @return the valid document root */ - final File getValidDirectory() { + public final File getValidDirectory() { File file = this.directory; file = (file != null) ? file : getWarFileDocumentRoot(); file = (file != null) ? file : getExplodedWarFileDocumentRoot(); diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/Jsp.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/Jsp.java similarity index 97% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/Jsp.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/Jsp.java index ef792a84f3..12f28bb80a 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/Jsp.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/Jsp.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.servlet.server; +package org.springframework.boot.web.server.servlet; import java.util.HashMap; import java.util.Map; @@ -26,7 +26,7 @@ import org.springframework.boot.context.properties.ConfigurationPropertiesSource * * @author Andy Wilkinson * @author Stephane Nicoll - * @since 2.0.0 + * @since 4.0.0 */ @ConfigurationPropertiesSource public class Jsp { diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/ServletContextInitializer.java similarity index 94% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializer.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/ServletContextInitializer.java index e71b6e9db8..86b618f878 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/ServletContextInitializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.servlet; +package org.springframework.boot.web.server.servlet; import jakarta.servlet.ServletContainerInitializer; import jakarta.servlet.ServletContext; @@ -37,7 +37,7 @@ import org.springframework.web.WebApplicationInitializer; * For configuration examples see {@link WebApplicationInitializer}. * * @author Phillip Webb - * @since 1.4.0 + * @since 4.0.0 * @see WebApplicationInitializer */ @FunctionalInterface diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/ServletContextInitializers.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/ServletContextInitializers.java new file mode 100644 index 0000000000..3d3ec2144d --- /dev/null +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/ServletContextInitializers.java @@ -0,0 +1,115 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.web.server.servlet; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.SessionCookieConfig; + +import org.springframework.boot.context.properties.PropertyMapper; +import org.springframework.boot.web.server.Cookie; +import org.springframework.boot.web.server.WebServer; + +/** + * The {@link ServletContextInitializer ServletContextInitializers} to apply to a servlet + * {@link WebServer}. + * + * @author Andy Wilkinson + * @since 4.0.0 + */ +public final class ServletContextInitializers implements Iterable { + + private final List initializers; + + private ServletContextInitializers(List initializers) { + this.initializers = initializers; + } + + @Override + public Iterator iterator() { + return this.initializers.iterator(); + } + + /** + * Creates a new instance from the given {@code settings} and {@code initializers}. + * @param settings the settings + * @param initializers the initializers + * @return the new instance + */ + public static ServletContextInitializers from(ServletWebServerSettings settings, + ServletContextInitializer... initializers) { + List mergedInitializers = new ArrayList<>(); + mergedInitializers + .add((servletContext) -> settings.getInitParameters().forEach(servletContext::setInitParameter)); + mergedInitializers.add(new SessionConfiguringInitializer(settings.getSession())); + mergedInitializers.addAll(Arrays.asList(initializers)); + mergedInitializers.addAll(settings.getInitializers()); + return new ServletContextInitializers(mergedInitializers); + } + + private static final class SessionConfiguringInitializer implements ServletContextInitializer { + + private final Session session; + + private SessionConfiguringInitializer(Session session) { + this.session = session; + } + + @Override + public void onStartup(ServletContext servletContext) throws ServletException { + if (this.session.getTrackingModes() != null) { + servletContext.setSessionTrackingModes(unwrap(this.session.getTrackingModes())); + } + configureSessionCookie(servletContext.getSessionCookieConfig()); + } + + private void configureSessionCookie(SessionCookieConfig config) { + Cookie cookie = this.session.getCookie(); + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); + map.from(cookie::getName).to(config::setName); + map.from(cookie::getDomain).to(config::setDomain); + map.from(cookie::getPath).to(config::setPath); + map.from(cookie::getHttpOnly).to(config::setHttpOnly); + map.from(cookie::getSecure).to(config::setSecure); + map.from(cookie::getMaxAge).asInt(Duration::getSeconds).to(config::setMaxAge); + map.from(cookie::getPartitioned) + .as(Object::toString) + .to((partitioned) -> config.setAttribute("Partitioned", partitioned)); + } + + private Set unwrap(Set modes) { + if (modes == null) { + return null; + } + Set result = new LinkedHashSet<>(); + for (Session.SessionTrackingMode mode : modes) { + result.add(jakarta.servlet.SessionTrackingMode.valueOf(mode.name())); + } + return result; + } + + } + +} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/ServletWebServerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/ServletWebServerFactory.java similarity index 88% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/ServletWebServerFactory.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/ServletWebServerFactory.java index 062148af6a..bb63a7c053 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/ServletWebServerFactory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/ServletWebServerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,17 +14,16 @@ * limitations under the License. */ -package org.springframework.boot.web.servlet.server; +package org.springframework.boot.web.server.servlet; import org.springframework.boot.web.server.WebServer; import org.springframework.boot.web.server.WebServerFactory; -import org.springframework.boot.web.servlet.ServletContextInitializer; /** * Factory interface that can be used to create a {@link WebServer}. * * @author Phillip Webb - * @since 2.0.0 + * @since 4.0.0 * @see WebServer */ @FunctionalInterface diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/ServletWebServerSettings.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/ServletWebServerSettings.java new file mode 100644 index 0000000000..3ab3c3be9d --- /dev/null +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/ServletWebServerSettings.java @@ -0,0 +1,188 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.web.server.servlet; + +import java.io.File; +import java.net.URL; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import org.springframework.boot.web.server.MimeMappings; +import org.springframework.boot.web.server.WebServer; +import org.springframework.util.Assert; + +/** + * Settings for a servlet {@link WebServer} to be created by a + * {@link ConfigurableServletWebServerFactory}. + * + * @author Andy Wilkinson + * @since 4.0.0 + */ +public class ServletWebServerSettings { + + private ContextPath contextPath = ContextPath.DEFAULT; + + private String displayName; + + private Session session = new Session(); + + private boolean registerDefaultServlet; + + private MimeMappings mimeMappings = MimeMappings.lazyCopy(MimeMappings.DEFAULT); + + private File documentRoot; + + private List initializers = new ArrayList<>(); + + private Jsp jsp = new Jsp(); + + private Map localeCharsetMappings = new HashMap<>(); + + private Map initParameters = new HashMap<>(); + + private List cookieSameSiteSuppliers = new ArrayList<>(); + + private final Set webListenerClassNames = new HashSet<>(); + + private final StaticResourceJars staticResourceJars = new StaticResourceJars(); + + public ContextPath getContextPath() { + return this.contextPath; + } + + public void setContextPath(ContextPath contextPath) { + this.contextPath = contextPath; + } + + public String getDisplayName() { + return this.displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public Session getSession() { + return this.session; + } + + public void setSession(Session session) { + this.session = session; + } + + public boolean isRegisterDefaultServlet() { + return this.registerDefaultServlet; + } + + public void setRegisterDefaultServlet(boolean registerDefaultServlet) { + this.registerDefaultServlet = registerDefaultServlet; + } + + public MimeMappings getMimeMappings() { + return this.mimeMappings; + } + + public File getDocumentRoot() { + return this.documentRoot; + } + + public void setDocumentRoot(File documentRoot) { + this.documentRoot = documentRoot; + } + + public List getInitializers() { + return this.initializers; + } + + public void setJsp(Jsp jsp) { + this.jsp = jsp; + } + + public Jsp getJsp() { + return this.jsp; + } + + public Map getLocaleCharsetMappings() { + return this.localeCharsetMappings; + } + + public Map getInitParameters() { + return this.initParameters; + } + + public List getCookieSameSiteSuppliers() { + return this.cookieSameSiteSuppliers; + } + + public void setMimeMappings(MimeMappings mimeMappings) { + Assert.notNull(mimeMappings, "'mimeMappings' must not be null"); + this.mimeMappings = new MimeMappings(mimeMappings); + } + + public void addMimeMappings(MimeMappings mimeMappings) { + mimeMappings.forEach((mapping) -> this.mimeMappings.add(mapping.getExtension(), mapping.getMimeType())); + } + + public void setInitializers(List initializers) { + Assert.notNull(initializers, "'initializers' must not be null"); + this.initializers = new ArrayList<>(initializers); + } + + public void addInitializers(ServletContextInitializer... initializers) { + Assert.notNull(initializers, "'initializers' must not be null"); + this.initializers.addAll(Arrays.asList(initializers)); + } + + public void setLocaleCharsetMappings(Map localeCharsetMappings) { + Assert.notNull(localeCharsetMappings, "'localeCharsetMappings' must not be null"); + this.localeCharsetMappings = localeCharsetMappings; + } + + public void setInitParameters(Map initParameters) { + this.initParameters = initParameters; + } + + public void setCookieSameSiteSuppliers(List cookieSameSiteSuppliers) { + Assert.notNull(cookieSameSiteSuppliers, "'cookieSameSiteSuppliers' must not be null"); + this.cookieSameSiteSuppliers = new ArrayList<>(cookieSameSiteSuppliers); + } + + public void addCookieSameSiteSuppliers(CookieSameSiteSupplier... cookieSameSiteSuppliers) { + Assert.notNull(cookieSameSiteSuppliers, "'cookieSameSiteSuppliers' must not be null"); + this.cookieSameSiteSuppliers.addAll(Arrays.asList(cookieSameSiteSuppliers)); + } + + public void addWebListenerClassNames(String... webListenerClassNames) { + this.webListenerClassNames.addAll(Arrays.asList(webListenerClassNames)); + } + + public Set getWebListenerClassNames() { + return this.webListenerClassNames; + } + + public List getStaticResourceUrls() { + return this.staticResourceJars.getUrls(); + } + +} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/Session.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/Session.java similarity index 96% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/Session.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/Session.java index 77f859cd19..4678ed9889 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/Session.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/Session.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.servlet.server; +package org.springframework.boot.web.server.servlet; import java.io.File; import java.time.Duration; @@ -30,7 +30,7 @@ import org.springframework.boot.web.server.Cookie; * Session properties. * * @author Andy Wilkinson - * @since 2.0.0 + * @since 4.0.0 */ @ConfigurationPropertiesSource public class Session { @@ -110,7 +110,7 @@ public class Session { return this.cookie; } - SessionStoreDirectory getSessionStoreDirectory() { + public SessionStoreDirectory getSessionStoreDirectory() { return this.sessionStoreDirectory; } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/SessionStoreDirectory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/SessionStoreDirectory.java similarity index 87% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/SessionStoreDirectory.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/SessionStoreDirectory.java index 810221fdfc..e13dc28243 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/SessionStoreDirectory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/SessionStoreDirectory.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.servlet.server; +package org.springframework.boot.web.server.servlet; import java.io.File; @@ -26,9 +26,9 @@ import org.springframework.util.Assert; * Manages a session store directory. * * @author Phillip Webb - * @see AbstractServletWebServerFactory + * @since 4.0.0 */ -class SessionStoreDirectory { +public class SessionStoreDirectory { private File directory; @@ -40,7 +40,7 @@ class SessionStoreDirectory { this.directory = directory; } - File getValidDirectory(boolean mkdirs) { + public File getValidDirectory(boolean mkdirs) { File dir = getDirectory(); if (dir == null) { return new ApplicationTemp().getDir("servlet-sessions"); diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/StaticResourceJars.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/StaticResourceJars.java similarity index 97% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/StaticResourceJars.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/StaticResourceJars.java index d23ef28452..36149b880a 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/StaticResourceJars.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/StaticResourceJars.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.servlet.server; +package org.springframework.boot.web.server.servlet; import java.io.File; import java.io.IOException; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/WebListenerRegistry.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/WebListenerRegistry.java similarity index 87% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/WebListenerRegistry.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/WebListenerRegistry.java index 68f0dde6e2..8ba4802929 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/WebListenerRegistry.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/WebListenerRegistry.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.servlet; +package org.springframework.boot.web.server.servlet; import jakarta.servlet.annotation.WebListener; @@ -22,12 +22,12 @@ import jakarta.servlet.annotation.WebListener; * A registry that holds {@link WebListener @WebListeners}. * * @author Andy Wilkinson - * @since 2.4.0 + * @since 4.0.0 */ public interface WebListenerRegistry { /** - * Adds web listeners that will be registered with the servlet container. + * Adds web listeners that will be registered with the servlet web server. * @param webListenerClassNames the class names of the web listeners */ void addWebListeners(String... webListenerClassNames); diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JasperInitializer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/jetty/JasperInitializer.java similarity index 97% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JasperInitializer.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/jetty/JasperInitializer.java index 5af413adf0..9544096b8a 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JasperInitializer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/jetty/JasperInitializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.jetty; +package org.springframework.boot.web.server.servlet.jetty; import java.io.IOException; import java.io.InputStream; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyEmbeddedErrorHandler.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/jetty/JettyEmbeddedErrorHandler.java similarity index 91% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyEmbeddedErrorHandler.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/jetty/JettyEmbeddedErrorHandler.java index 924a532421..89d399eff4 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyEmbeddedErrorHandler.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/jetty/JettyEmbeddedErrorHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.jetty; +package org.springframework.boot.web.server.servlet.jetty; import org.eclipse.jetty.ee10.servlet.ErrorPageErrorHandler; import org.eclipse.jetty.http.HttpMethod; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyEmbeddedWebAppContext.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/jetty/JettyEmbeddedWebAppContext.java similarity index 90% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyEmbeddedWebAppContext.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/jetty/JettyEmbeddedWebAppContext.java index 625e7b822f..57ba544f12 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyEmbeddedWebAppContext.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/jetty/JettyEmbeddedWebAppContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,12 +14,14 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.jetty; +package org.springframework.boot.web.server.servlet.jetty; import org.eclipse.jetty.ee10.servlet.ServletHandler; import org.eclipse.jetty.ee10.webapp.WebAppContext; import org.eclipse.jetty.util.ClassMatcher; +import org.springframework.boot.web.server.jetty.JettyWebServer; + /** * Jetty {@link WebAppContext} used by {@link JettyWebServer} to support deferred * initialization. diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/jetty/JettyServletWebServer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/jetty/JettyServletWebServer.java new file mode 100644 index 0000000000..c4ef36f300 --- /dev/null +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/jetty/JettyServletWebServer.java @@ -0,0 +1,65 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.web.server.servlet.jetty; + +import java.util.List; + +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.Server; + +import org.springframework.boot.web.server.jetty.JettyWebServer; + +/** + * Servlet-specific {@link JettyWebServer}. + * + * @author Andy Wilkinson + * @since 4.0.0 + */ +public class JettyServletWebServer extends JettyWebServer { + + public JettyServletWebServer(Server server) { + super(server); + } + + public JettyServletWebServer(Server server, boolean autoStart) { + super(server, autoStart); + } + + @Override + protected void handleDeferredInitialize(Server server) throws Exception { + handleDeferredInitialize(server.getHandlers()); + } + + protected void handleDeferredInitialize(List handlers) throws Exception { + for (Handler handler : handlers) { + handleDeferredInitialize(handler); + } + } + + private void handleDeferredInitialize(Handler handler) throws Exception { + if (handler instanceof JettyEmbeddedWebAppContext jettyEmbeddedWebAppContext) { + jettyEmbeddedWebAppContext.deferredInitialize(); + } + else if (handler instanceof Handler.Wrapper handlerWrapper) { + handleDeferredInitialize(handlerWrapper.getHandler()); + } + else if (handler instanceof Handler.Collection handlerCollection) { + handleDeferredInitialize(handlerCollection.getHandlers()); + } + } + +} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/jetty/JettyServletWebServerFactory.java similarity index 72% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactory.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/jetty/JettyServletWebServerFactory.java index 6bdd590c68..27077f5301 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/jetty/JettyServletWebServerFactory.java @@ -14,23 +14,23 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.jetty; +package org.springframework.boot.web.server.servlet.jetty; import java.io.File; import java.net.InetSocketAddress; import java.net.URL; import java.time.Duration; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.EventListener; -import java.util.LinkedHashSet; import java.util.List; import java.util.Objects; import java.util.Set; import java.util.UUID; import jakarta.servlet.http.Cookie; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.eclipse.jetty.ee10.servlet.ErrorHandler; import org.eclipse.jetty.ee10.servlet.ErrorPageErrorHandler; import org.eclipse.jetty.ee10.servlet.ListenerHolder; @@ -52,19 +52,13 @@ import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.http.MimeTypes.Wrapper; import org.eclipse.jetty.http.SetCookieParser; -import org.eclipse.jetty.http2.server.HTTP2CServerConnectionFactory; -import org.eclipse.jetty.server.AbstractConnector; -import org.eclipse.jetty.server.ConnectionFactory; import org.eclipse.jetty.server.ConnectionLimit; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Handler; -import org.eclipse.jetty.server.HttpConfiguration; -import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.HttpCookieUtils; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Response; import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.handler.StatisticsHandler; import org.eclipse.jetty.session.DefaultSessionCache; import org.eclipse.jetty.session.FileSessionDataStore; @@ -73,7 +67,6 @@ import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.resource.ResourceFactory; import org.eclipse.jetty.util.resource.URLResourceFactory; -import org.eclipse.jetty.util.thread.ThreadPool; import org.springframework.boot.web.server.Cookie.SameSite; import org.springframework.boot.web.server.ErrorPage; @@ -81,13 +74,23 @@ import org.springframework.boot.web.server.MimeMappings; import org.springframework.boot.web.server.Shutdown; import org.springframework.boot.web.server.Ssl; import org.springframework.boot.web.server.WebServer; -import org.springframework.boot.web.servlet.ServletContextInitializer; -import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactory; -import org.springframework.boot.web.servlet.server.CookieSameSiteSupplier; -import org.springframework.boot.web.servlet.server.ServletWebServerFactory; +import org.springframework.boot.web.server.jetty.ConfigurableJettyWebServerFactory; +import org.springframework.boot.web.server.jetty.ForwardHeadersCustomizer; +import org.springframework.boot.web.server.jetty.JettyServerCustomizer; +import org.springframework.boot.web.server.jetty.JettyWebServer; +import org.springframework.boot.web.server.jetty.JettyWebServerFactory; +import org.springframework.boot.web.server.servlet.ConfigurableServletWebServerFactory; +import org.springframework.boot.web.server.servlet.ContextPath; +import org.springframework.boot.web.server.servlet.CookieSameSiteSupplier; +import org.springframework.boot.web.server.servlet.DocumentRoot; +import org.springframework.boot.web.server.servlet.ServletContextInitializer; +import org.springframework.boot.web.server.servlet.ServletContextInitializers; +import org.springframework.boot.web.server.servlet.ServletWebServerFactory; +import org.springframework.boot.web.server.servlet.ServletWebServerSettings; import org.springframework.context.ResourceLoaderAware; import org.springframework.core.io.ResourceLoader; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; @@ -108,36 +111,20 @@ import org.springframework.util.StringUtils; * @author Henri Kerola * @author Moritz Halbritter * @author Onur Kagan Ozcan - * @since 2.0.0 + * @since 4.0.0 * @see #setPort(int) * @see #setConfigurations(Collection) * @see JettyWebServer */ -public class JettyServletWebServerFactory extends AbstractServletWebServerFactory - implements ConfigurableJettyWebServerFactory, ResourceLoaderAware { +public class JettyServletWebServerFactory extends JettyWebServerFactory + implements ConfigurableJettyWebServerFactory, ConfigurableServletWebServerFactory, ResourceLoaderAware { - private List configurations = new ArrayList<>(); + private static final Log logger = LogFactory.getLog(JettyServletWebServerFactory.class); - private boolean useForwardHeaders; - - /** - * The number of acceptor threads to use. - */ - private int acceptors = -1; - - /** - * The number of selector threads to use. - */ - private int selectors = -1; - - private Set jettyServerCustomizers = new LinkedHashSet<>(); + private final ServletWebServerSettings settings = new ServletWebServerSettings(); private ResourceLoader resourceLoader; - private ThreadPool threadPool; - - private int maxConnections = -1; - /** * Create a new {@link JettyServletWebServerFactory} instance. */ @@ -160,7 +147,8 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor * @param port the port to listen on */ public JettyServletWebServerFactory(String contextPath, int port) { - super(contextPath, port); + super(port); + getSettings().setContextPath(ContextPath.of(contextPath)); } @Override @@ -173,9 +161,9 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor context.setServer(server); configureWebAppContext(context, initializers); server.setHandler(addHandlerWrappers(context)); - this.logger.info("Server initialized with port: " + port); - if (this.maxConnections > -1) { - server.addBean(new ConnectionLimit(this.maxConnections, server.getConnectors())); + logger.info("Server initialized with port: " + port); + if (this.getMaxConnections() > -1) { + server.addBean(new ConnectionLimit(this.getMaxConnections(), server.getConnectors())); } if (Ssl.isEnabled(getSsl())) { customizeSsl(server, address); @@ -183,7 +171,7 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor for (JettyServerCustomizer customizer : getServerCustomizers()) { customizer.customize(server); } - if (this.useForwardHeaders) { + if (this.isUseForwardHeaders()) { new ForwardHeadersCustomizer().customize(server); } if (getShutdown() == Shutdown.GRACEFUL) { @@ -199,56 +187,27 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor server.setConnectors(new Connector[] { createConnector(address, server) }); server.setStopTimeout(0); MimeTypes.Mutable mimeTypes = server.getMimeTypes(); - for (MimeMappings.Mapping mapping : getMimeMappings()) { + for (MimeMappings.Mapping mapping : getSettings().getMimeMappings()) { mimeTypes.addMimeMapping(mapping.getExtension(), mapping.getMimeType()); } return server; } - private AbstractConnector createConnector(InetSocketAddress address, Server server) { - HttpConfiguration httpConfiguration = new HttpConfiguration(); - httpConfiguration.setSendServerVersion(false); - List connectionFactories = new ArrayList<>(); - connectionFactories.add(new HttpConnectionFactory(httpConfiguration)); - if (getHttp2() != null && getHttp2().isEnabled()) { - connectionFactories.add(new HTTP2CServerConnectionFactory(httpConfiguration)); - } - ServerConnector connector = new ServerConnector(server, this.acceptors, this.selectors, - connectionFactories.toArray(new ConnectionFactory[0])); - connector.setHost(address.getHostString()); - connector.setPort(address.getPort()); - return connector; - } - - private Handler addHandlerWrappers(Handler handler) { - if (getCompression() != null && getCompression().getEnabled()) { - handler = applyWrapper(handler, JettyHandlerWrappers.createGzipHandlerWrapper(getCompression())); - } - if (StringUtils.hasText(getServerHeader())) { - handler = applyWrapper(handler, JettyHandlerWrappers.createServerHeaderHandlerWrapper(getServerHeader())); - } - if (!CollectionUtils.isEmpty(getCookieSameSiteSuppliers())) { - handler = applyWrapper(handler, - new SuppliedSameSiteCookieHandlerWrapper(getSessionCookieName(), getCookieSameSiteSuppliers())); + @Override + protected Handler addHandlerWrappers(Handler handler) { + handler = super.addHandlerWrappers(handler); + if (!CollectionUtils.isEmpty(getSettings().getCookieSameSiteSuppliers())) { + handler = applyWrapper(handler, new SuppliedSameSiteCookieHandlerWrapper(getSessionCookieName(), + getSettings().getCookieSameSiteSuppliers())); } return handler; } private String getSessionCookieName() { - String name = getSession().getCookie().getName(); + String name = getSettings().getSession().getCookie().getName(); return (name != null) ? name : SessionConfig.__DefaultSessionCookie; } - private Handler applyWrapper(Handler handler, Handler.Wrapper wrapper) { - wrapper.setHandler(handler); - return wrapper; - } - - private void customizeSsl(Server server, InetSocketAddress address) { - Assert.state(getSsl().getServerNameBundles().isEmpty(), "Server name SSL bundles are not supported with Jetty"); - new SslServerCustomizer(getHttp2(), address, getSsl().getClientAuth(), getSslBundle()).customize(server); - } - /** * Configure the given Jetty {@link WebAppContext} for use. * @param context the context to configure @@ -260,11 +219,11 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor if (this.resourceLoader != null) { context.setClassLoader(this.resourceLoader.getClassLoader()); } - String contextPath = getContextPath(); + String contextPath = getSettings().getContextPath().toString(); context.setContextPath(StringUtils.hasLength(contextPath) ? contextPath : "/"); - context.setDisplayName(getDisplayName()); + context.setDisplayName(getSettings().getDisplayName()); configureDocumentRoot(context); - if (isRegisterDefaultServlet()) { + if (getSettings().isRegisterDefaultServlet()) { addDefaultServlet(context); } if (shouldRegisterJspServlet()) { @@ -272,7 +231,7 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor context.addBean(new JasperInitializer(context), true); } addLocaleMappings(context); - ServletContextInitializer[] initializersToUse = mergeInitializers(initializers); + ServletContextInitializers initializersToUse = ServletContextInitializers.from(this.settings, initializers); Configuration[] configurations = getWebAppContextConfigurations(context, initializersToUse); context.setConfigurations(configurations); context.setThrowUnavailableOnStartupException(true); @@ -281,18 +240,23 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor postProcessWebAppContext(context); } + private boolean shouldRegisterJspServlet() { + return this.settings.getJsp() != null && this.settings.getJsp().getRegistered() + && ClassUtils.isPresent(this.settings.getJsp().getClassName(), getClass().getClassLoader()); + } + private void configureSession(WebAppContext context) { SessionHandler handler = context.getSessionHandler(); - SameSite sessionSameSite = getSession().getCookie().getSameSite(); + SameSite sessionSameSite = getSettings().getSession().getCookie().getSameSite(); if (sessionSameSite != null && sessionSameSite != SameSite.OMITTED) { handler.setSameSite(HttpCookie.SameSite.valueOf(sessionSameSite.name())); } - Duration sessionTimeout = getSession().getTimeout(); + Duration sessionTimeout = getSettings().getSession().getTimeout(); handler.setMaxInactiveInterval(isNegative(sessionTimeout) ? -1 : (int) sessionTimeout.getSeconds()); - if (getSession().isPersistent()) { + if (getSettings().getSession().isPersistent()) { DefaultSessionCache cache = new DefaultSessionCache(handler); FileSessionDataStore store = new FileSessionDataStore(); - store.setStoreDir(getValidSessionStoreDir()); + store.setStoreDir(getSettings().getSession().getSessionStoreDirectory().getValidDirectory(true)); cache.setSessionDataStore(store); handler.setSessionCache(cache); } @@ -303,7 +267,7 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor } private void addLocaleMappings(WebAppContext context) { - getLocaleCharsetMappings() + getSettings().getLocaleCharsetMappings() .forEach((locale, charset) -> context.addLocaleEncoding(locale.toString(), charset.toString())); } @@ -323,7 +287,9 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor } private void configureDocumentRoot(WebAppContext handler) { - File root = getValidDocumentRoot(); + DocumentRoot documentRoot = new DocumentRoot(logger); + documentRoot.setDirectory(this.settings.getDocumentRoot()); + File root = documentRoot.getValidDirectory(); File docBase = (root != null) ? root : createTempDir("jetty-docbase"); try { ResourceFactory resourceFactory = handler.getResourceFactory(); @@ -333,7 +299,7 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor : resourceFactory.newJarFileResource(docBase.toURI())); resources.add((root != null) ? new LoaderHidingResource(rootResource, rootResource) : rootResource); URLResourceFactory urlResourceFactory = new URLResourceFactory(); - for (URL resourceJarUrl : getUrlsOfJarsWithMetaInfResources()) { + for (URL resourceJarUrl : getSettings().getStaticResourceUrls()) { Resource resource = createResource(resourceJarUrl, resourceFactory, urlResourceFactory); if (resource != null) { resources.add(resource); @@ -384,9 +350,9 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor Assert.notNull(context, "'context' must not be null"); ServletHolder holder = new ServletHolder(); holder.setName("jsp"); - holder.setClassName(getJsp().getClassName()); + holder.setClassName(this.settings.getJsp().getClassName()); holder.setInitParameter("fork", "false"); - holder.setInitParameters(getJsp().getInitParameters()); + holder.setInitParameters(this.settings.getJsp().getInitParameters()); holder.setInitOrder(3); context.getServletHandler().addServlet(holder); ServletMapping mapping = new ServletMapping(); @@ -402,12 +368,12 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor * @return configurations to apply */ protected Configuration[] getWebAppContextConfigurations(WebAppContext webAppContext, - ServletContextInitializer... initializers) { + ServletContextInitializers initializers) { List configurations = new ArrayList<>(); configurations.add(getServletContextInitializerConfiguration(webAppContext, initializers)); configurations.add(getErrorPageConfiguration()); configurations.add(getMimeTypeConfiguration()); - configurations.add(new WebListenersConfiguration(getWebListenerClassNames())); + configurations.add(new WebListenersConfiguration(getSettings().getWebListenerClassNames())); configurations.addAll(getConfigurations()); return configurations.toArray(new Configuration[0]); } @@ -440,7 +406,7 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor public void configure(WebAppContext context) throws Exception { MimeTypes.Wrapper mimeTypes = (Wrapper) context.getMimeTypes(); mimeTypes.setWrapped(new MimeTypes(null)); - for (MimeMappings.Mapping mapping : getMimeMappings()) { + for (MimeMappings.Mapping mapping : getSettings().getMimeMappings()) { mimeTypes.addMimeMapping(mapping.getExtension(), mapping.getMimeType()); } } @@ -457,7 +423,7 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor * @return the {@link Configuration} instance */ protected Configuration getServletContextInitializerConfiguration(WebAppContext webAppContext, - ServletContextInitializer... initializers) { + ServletContextInitializers initializers) { return new ServletContextInitializerConfiguration(initializers); } @@ -478,7 +444,7 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor * @return a new {@link JettyWebServer} instance */ protected JettyWebServer getJettyWebServer(Server server) { - return new JettyWebServer(server, getPort() >= 0); + return new JettyServletWebServer(server, getPort() >= 0); } @Override @@ -486,94 +452,6 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor this.resourceLoader = resourceLoader; } - @Override - public void setUseForwardHeaders(boolean useForwardHeaders) { - this.useForwardHeaders = useForwardHeaders; - } - - @Override - public void setAcceptors(int acceptors) { - this.acceptors = acceptors; - } - - @Override - public void setSelectors(int selectors) { - this.selectors = selectors; - } - - @Override - public void setMaxConnections(int maxConnections) { - this.maxConnections = maxConnections; - } - - /** - * Sets {@link JettyServerCustomizer}s that will be applied to the {@link Server} - * before it is started. Calling this method will replace any existing customizers. - * @param customizers the Jetty customizers to apply - */ - public void setServerCustomizers(Collection customizers) { - Assert.notNull(customizers, "'customizers' must not be null"); - this.jettyServerCustomizers = new LinkedHashSet<>(customizers); - } - - /** - * Returns a mutable collection of Jetty {@link JettyServerCustomizer}s that will be - * applied to the {@link Server} before it is created. - * @return the {@link JettyServerCustomizer}s - */ - public Collection getServerCustomizers() { - return this.jettyServerCustomizers; - } - - @Override - public void addServerCustomizers(JettyServerCustomizer... customizers) { - Assert.notNull(customizers, "'customizers' must not be null"); - this.jettyServerCustomizers.addAll(Arrays.asList(customizers)); - } - - /** - * Sets Jetty {@link Configuration}s that will be applied to the {@link WebAppContext} - * before the server is created. Calling this method will replace any existing - * configurations. - * @param configurations the Jetty configurations to apply - */ - public void setConfigurations(Collection configurations) { - Assert.notNull(configurations, "'configurations' must not be null"); - this.configurations = new ArrayList<>(configurations); - } - - /** - * Returns a mutable collection of Jetty {@link Configuration}s that will be applied - * to the {@link WebAppContext} before the server is created. - * @return the Jetty {@link Configuration}s - */ - public Collection getConfigurations() { - return this.configurations; - } - - /** - * Add {@link Configuration}s that will be applied to the {@link WebAppContext} before - * the server is started. - * @param configurations the configurations to add - */ - public void addConfigurations(Configuration... configurations) { - Assert.notNull(configurations, "'configurations' must not be null"); - 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; - } - - @Override - public void setThreadPool(ThreadPool threadPool) { - this.threadPool = threadPool; - } - private void addJettyErrorPages(ErrorHandler errorHandler, Collection errorPages) { if (errorHandler instanceof ErrorPageErrorHandler handler) { for (ErrorPage errorPage : errorPages) { @@ -592,6 +470,11 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor } } + @Override + public ServletWebServerSettings getSettings() { + return this.settings; + } + /** * {@link AbstractConfiguration} to apply {@code @WebListener} classes. */ @@ -639,9 +522,10 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor private final String sessionCookieName; - private final List suppliers; + private final List suppliers; - SuppliedSameSiteCookieHandlerWrapper(String sessionCookieName, List suppliers) { + SuppliedSameSiteCookieHandlerWrapper(String sessionCookieName, + List suppliers) { this.sessionCookieName = sessionCookieName; this.suppliers = suppliers; } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/LoaderHidingResource.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/jetty/LoaderHidingResource.java similarity index 97% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/LoaderHidingResource.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/jetty/LoaderHidingResource.java index ed42fc05dd..eac7b14e53 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/LoaderHidingResource.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/jetty/LoaderHidingResource.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.jetty; +package org.springframework.boot.web.server.servlet.jetty; import java.io.IOException; import java.io.InputStream; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/ServletContextInitializerConfiguration.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/jetty/ServletContextInitializerConfiguration.java similarity index 82% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/ServletContextInitializerConfiguration.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/jetty/ServletContextInitializerConfiguration.java index fdae324260..1ce17dccce 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/ServletContextInitializerConfiguration.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/jetty/ServletContextInitializerConfiguration.java @@ -14,14 +14,15 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.jetty; +package org.springframework.boot.web.server.servlet.jetty; import jakarta.servlet.ServletException; import org.eclipse.jetty.ee10.webapp.AbstractConfiguration; import org.eclipse.jetty.ee10.webapp.Configuration; import org.eclipse.jetty.ee10.webapp.WebAppContext; -import org.springframework.boot.web.servlet.ServletContextInitializer; +import org.springframework.boot.web.server.servlet.ServletContextInitializer; +import org.springframework.boot.web.server.servlet.ServletContextInitializers; import org.springframework.util.Assert; /** @@ -29,18 +30,16 @@ import org.springframework.util.Assert; * * @author Phillip Webb * @author Andy Wilkinson - * @since 2.0.0 */ -public class ServletContextInitializerConfiguration extends AbstractConfiguration { +class ServletContextInitializerConfiguration extends AbstractConfiguration { - private final ServletContextInitializer[] initializers; + private final ServletContextInitializers initializers; /** * Create a new {@link ServletContextInitializerConfiguration}. * @param initializers the initializers that should be invoked - * @since 1.2.1 */ - public ServletContextInitializerConfiguration(ServletContextInitializer... initializers) { + ServletContextInitializerConfiguration(ServletContextInitializers initializers) { super(new AbstractConfiguration.Builder()); Assert.notNull(initializers, "'initializers' must not be null"); this.initializers = initializers; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/jetty/package-info.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/jetty/package-info.java new file mode 100644 index 0000000000..1cdd74ea4e --- /dev/null +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/jetty/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Servlet web server implementation backed by Jetty. + */ +package org.springframework.boot.web.server.servlet.jetty; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/package-info.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/package-info.java new file mode 100644 index 0000000000..98ac8b5c87 --- /dev/null +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Servlet web server abstractions. + */ +package org.springframework.boot.web.server.servlet; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/NestedJarResourceSet.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/tomcat/NestedJarResourceSet.java similarity index 97% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/NestedJarResourceSet.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/tomcat/NestedJarResourceSet.java index 6e6606c6a6..4027b75867 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/NestedJarResourceSet.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/tomcat/NestedJarResourceSet.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.tomcat; +package org.springframework.boot.web.server.servlet.tomcat; import java.io.IOException; import java.net.JarURLConnection; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TldPatterns.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/tomcat/TldPatterns.java similarity index 98% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TldPatterns.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/tomcat/TldPatterns.java index 69ab0f7854..494f2e1f55 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TldPatterns.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/tomcat/TldPatterns.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.tomcat; +package org.springframework.boot.web.server.servlet.tomcat; import java.util.Collections; import java.util.LinkedHashSet; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/tomcat/TomcatServletWebServerFactory.java similarity index 55% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactory.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/tomcat/TomcatServletWebServerFactory.java index 923184d3cd..4d35239165 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/tomcat/TomcatServletWebServerFactory.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.tomcat; +package org.springframework.boot.web.server.servlet.tomcat; import java.io.File; import java.io.InputStream; @@ -38,8 +38,6 @@ import jakarta.servlet.ServletContainerInitializer; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import org.apache.catalina.Context; -import org.apache.catalina.Engine; -import org.apache.catalina.Executor; import org.apache.catalina.Host; import org.apache.catalina.Lifecycle; import org.apache.catalina.LifecycleEvent; @@ -52,8 +50,6 @@ import org.apache.catalina.WebResourceRoot; import org.apache.catalina.WebResourceRoot.ResourceSetType; import org.apache.catalina.WebResourceSet; import org.apache.catalina.Wrapper; -import org.apache.catalina.connector.Connector; -import org.apache.catalina.core.AprLifecycleListener; import org.apache.catalina.loader.WebappLoader; import org.apache.catalina.session.StandardManager; import org.apache.catalina.startup.Tomcat; @@ -65,24 +61,29 @@ import org.apache.catalina.webresources.EmptyResource; import org.apache.catalina.webresources.StandardRoot; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.coyote.AbstractProtocol; -import org.apache.coyote.ProtocolHandler; -import org.apache.coyote.http2.Http2Protocol; import org.apache.tomcat.util.http.Rfc6265CookieProcessor; -import org.apache.tomcat.util.modeler.Registry; import org.apache.tomcat.util.scan.StandardJarScanFilter; -import org.springframework.boot.util.LambdaSafe; import org.springframework.boot.web.server.Cookie.SameSite; import org.springframework.boot.web.server.ErrorPage; import org.springframework.boot.web.server.MimeMappings; -import org.springframework.boot.web.server.Ssl; import org.springframework.boot.web.server.WebServer; -import org.springframework.boot.web.servlet.ServletContextInitializer; -import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactory; -import org.springframework.boot.web.servlet.server.CookieSameSiteSupplier; +import org.springframework.boot.web.server.servlet.ConfigurableServletWebServerFactory; +import org.springframework.boot.web.server.servlet.ContextPath; +import org.springframework.boot.web.server.servlet.CookieSameSiteSupplier; +import org.springframework.boot.web.server.servlet.DocumentRoot; +import org.springframework.boot.web.server.servlet.ServletContextInitializer; +import org.springframework.boot.web.server.servlet.ServletContextInitializers; +import org.springframework.boot.web.server.servlet.ServletWebServerSettings; +import org.springframework.boot.web.server.tomcat.ConfigurableTomcatWebServerFactory; +import org.springframework.boot.web.server.tomcat.DisableReferenceClearingContextCustomizer; +import org.springframework.boot.web.server.tomcat.TomcatContextCustomizer; +import org.springframework.boot.web.server.tomcat.TomcatEmbeddedContext; +import org.springframework.boot.web.server.tomcat.TomcatEmbeddedWebappClassLoader; +import org.springframework.boot.web.server.tomcat.TomcatStarter; +import org.springframework.boot.web.server.tomcat.TomcatWebServer; +import org.springframework.boot.web.server.tomcat.TomcatWebServerFactory; import org.springframework.context.ResourceLoaderAware; -import org.springframework.core.NativeDetector; import org.springframework.core.io.ResourceLoader; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -91,7 +92,7 @@ import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; /** - * {@link AbstractServletWebServerFactory} that can be used to create + * {@link ConfigurableServletWebServerFactory} that can be used to create * {@link TomcatWebServer}s. Can be initialized using Spring's * {@link ServletContextInitializer}s or Tomcat {@link LifecycleListener}s. *

@@ -108,13 +109,13 @@ import org.springframework.util.StringUtils; * @author Dawid Antecki * @author Moritz Halbritter * @author Scott Frederick - * @since 2.0.0 + * @since 4.0.0 * @see #setPort(int) * @see #setContextLifecycleListeners(Collection) * @see TomcatWebServer */ -public class TomcatServletWebServerFactory extends AbstractServletWebServerFactory - implements ConfigurableTomcatWebServerFactory, ResourceLoaderAware { +public class TomcatServletWebServerFactory extends TomcatWebServerFactory + implements ConfigurableTomcatWebServerFactory, ConfigurableServletWebServerFactory, ResourceLoaderAware { private static final Log logger = LogFactory.getLog(TomcatServletWebServerFactory.class); @@ -122,43 +123,14 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto private static final Set> NO_CLASSES = Collections.emptySet(); - /** - * The class name of default protocol used. - */ - public static final String DEFAULT_PROTOCOL = "org.apache.coyote.http11.Http11NioProtocol"; - - private File baseDirectory; - - private List engineValves = new ArrayList<>(); - - private List contextValves = new ArrayList<>(); - - private List contextLifecycleListeners = new ArrayList<>(); - - private Set tomcatContextCustomizers = new LinkedHashSet<>(); - - private Set tomcatConnectorCustomizers = new LinkedHashSet<>(); - - private Set> tomcatProtocolHandlerCustomizers = new LinkedHashSet<>(); - - private final List additionalTomcatConnectors = new ArrayList<>(); + private final ServletWebServerSettings settings = new ServletWebServerSettings(); private ResourceLoader resourceLoader; - private String protocol = DEFAULT_PROTOCOL; - private Set tldSkipPatterns = new LinkedHashSet<>(TldPatterns.DEFAULT_SKIP); private final Set tldScanPatterns = new LinkedHashSet<>(TldPatterns.DEFAULT_SCAN); - private Charset uriEncoding = DEFAULT_CHARSET; - - private int backgroundProcessorDelay; - - private boolean disableMBeanRegistry = true; - - private boolean useApr; - /** * Create a new {@link TomcatServletWebServerFactory} instance. */ @@ -181,68 +153,31 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto * @param port the port to listen on */ public TomcatServletWebServerFactory(String contextPath, int port) { - super(contextPath, port); - } - - private List getDefaultServerLifecycleListeners() { - ArrayList lifecycleListeners = new ArrayList<>(); - if (!NativeDetector.inNativeImage() && this.useApr) { - lifecycleListeners.add(new AprLifecycleListener()); - } - return lifecycleListeners; + super(port); + this.settings.setContextPath(ContextPath.of(contextPath)); } @Override public WebServer getWebServer(ServletContextInitializer... initializers) { - if (this.disableMBeanRegistry) { - Registry.disableRegistry(); - } - Tomcat tomcat = new Tomcat(); - File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat"); - tomcat.setBaseDir(baseDir.getAbsolutePath()); - for (LifecycleListener listener : getDefaultServerLifecycleListeners()) { - tomcat.getServer().addLifecycleListener(listener); - } - Connector connector = new Connector(this.protocol); - connector.setThrowOnFailure(true); - tomcat.getService().addConnector(connector); - customizeConnector(connector); - tomcat.setConnector(connector); - registerConnectorExecutor(tomcat, connector); - tomcat.getHost().setAutoDeploy(false); - configureEngine(tomcat.getEngine()); - for (Connector additionalConnector : this.additionalTomcatConnectors) { - tomcat.getService().addConnector(additionalConnector); - registerConnectorExecutor(tomcat, additionalConnector); - } + Tomcat tomcat = createTomcat(); prepareContext(tomcat.getHost(), initializers); return getTomcatWebServer(tomcat); } - private void registerConnectorExecutor(Tomcat tomcat, Connector connector) { - if (connector.getProtocolHandler().getExecutor() instanceof Executor executor) { - tomcat.getService().addExecutor(executor); - } - } - - private void configureEngine(Engine engine) { - engine.setBackgroundProcessorDelay(this.backgroundProcessorDelay); - for (Valve valve : this.engineValves) { - engine.getPipeline().addValve(valve); - } - } - protected void prepareContext(Host host, ServletContextInitializer[] initializers) { - File documentRoot = getValidDocumentRoot(); + DocumentRoot documentRoot = new DocumentRoot(logger); + documentRoot.setDirectory(this.settings.getDocumentRoot()); + File documentRootFile = documentRoot.getValidDirectory(); TomcatEmbeddedContext context = new TomcatEmbeddedContext(); - WebResourceRoot resourceRoot = (documentRoot != null) ? new LoaderHidingResourceRoot(context) + WebResourceRoot resourceRoot = (documentRootFile != null) ? new LoaderHidingResourceRoot(context) : new StandardRoot(context); ignoringNoSuchMethodError(() -> resourceRoot.setReadOnly(true)); context.setResources(resourceRoot); - context.setName(getContextPath()); - context.setDisplayName(getDisplayName()); - context.setPath(getContextPath()); - File docBase = (documentRoot != null) ? documentRoot : createTempDir("tomcat-docbase"); + String contextPath = this.settings.getContextPath().toString(); + context.setName(contextPath); + context.setDisplayName(this.settings.getDisplayName()); + context.setPath(contextPath); + File docBase = (documentRootFile != null) ? documentRootFile : createTempDir("tomcat-docbase"); context.setDocBase(docBase.getAbsolutePath()); context.addLifecycleListener(new FixContextListener()); ClassLoader parentClassLoader = (this.resourceLoader != null) ? this.resourceLoader.getClassLoader() @@ -256,7 +191,7 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto loader.setLoaderInstance(new TomcatEmbeddedWebappClassLoader(parentClassLoader)); loader.setDelegate(true); context.setLoader(loader); - if (isRegisterDefaultServlet()) { + if (this.settings.isRegisterDefaultServlet()) { addDefaultServlet(context); } if (shouldRegisterJspServlet()) { @@ -264,7 +199,7 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto addJasperInitializer(context); } context.addLifecycleListener(new StaticResourceConfigurer(context)); - ServletContextInitializer[] initializersToUse = mergeInitializers(initializers); + ServletContextInitializers initializersToUse = ServletContextInitializers.from(this.settings, initializers); host.addChild(context); configureContext(context, initializersToUse); postProcessContext(context); @@ -278,6 +213,11 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto } } + private boolean shouldRegisterJspServlet() { + return this.settings.getJsp() != null && this.settings.getJsp().getRegistered() + && ClassUtils.isPresent(this.settings.getJsp().getClassName(), getClass().getClassLoader()); + } + /** * Override Tomcat's default locale mappings to align with other servers. See * {@code org.apache.catalina.util.CharsetMapperDefault.properties}. @@ -290,8 +230,9 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto } private void addLocaleMappings(TomcatEmbeddedContext context) { - getLocaleCharsetMappings().forEach( - (locale, charset) -> context.addLocaleEncodingMappingParameter(locale.toString(), charset.toString())); + this.settings.getLocaleCharsetMappings() + .forEach((locale, charset) -> context.addLocaleEncodingMappingParameter(locale.toString(), + charset.toString())); } private void configureTldPatterns(TomcatEmbeddedContext context) { @@ -317,9 +258,9 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto private void addJspServlet(Context context) { Wrapper jspServlet = context.createWrapper(); jspServlet.setName("jsp"); - jspServlet.setServletClass(getJsp().getClassName()); + jspServlet.setServletClass(this.settings.getJsp().getClassName()); jspServlet.addInitParameter("fork", "false"); - getJsp().getInitParameters().forEach(jspServlet::addInitParameter); + this.settings.getJsp().getInitParameters().forEach(jspServlet::addInitParameter); jspServlet.setLoadOnStartup(3); context.addChild(jspServlet); context.addServletMappingDecoded("*.jsp", "jsp"); @@ -339,78 +280,22 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto } } - // Needs to be protected so it can be used by subclasses - protected void customizeConnector(Connector connector) { - int port = Math.max(getPort(), 0); - connector.setPort(port); - if (StringUtils.hasText(getServerHeader())) { - connector.setProperty("server", getServerHeader()); - } - if (connector.getProtocolHandler() instanceof AbstractProtocol abstractProtocol) { - customizeProtocol(abstractProtocol); - } - invokeProtocolHandlerCustomizers(connector.getProtocolHandler()); - if (getUriEncoding() != null) { - connector.setURIEncoding(getUriEncoding().name()); - } - if (getHttp2() != null && getHttp2().isEnabled()) { - connector.addUpgradeProtocol(new Http2Protocol()); - } - if (Ssl.isEnabled(getSsl())) { - customizeSsl(connector); - } - TomcatConnectorCustomizer compression = new CompressionConnectorCustomizer(getCompression()); - compression.customize(connector); - for (TomcatConnectorCustomizer customizer : this.tomcatConnectorCustomizers) { - customizer.customize(connector); - } - } - - private void customizeProtocol(AbstractProtocol protocol) { - if (getAddress() != null) { - protocol.setAddress(getAddress()); - } - } - - @SuppressWarnings("unchecked") - private void invokeProtocolHandlerCustomizers(ProtocolHandler protocolHandler) { - LambdaSafe - .callbacks(TomcatProtocolHandlerCustomizer.class, this.tomcatProtocolHandlerCustomizers, protocolHandler) - .invoke((customizer) -> customizer.customize(protocolHandler)); - } - - private void customizeSsl(Connector connector) { - SslConnectorCustomizer customizer = new SslConnectorCustomizer(logger, connector, getSsl().getClientAuth()); - customizer.customize(getSslBundle(), getServerNameSslBundles()); - addBundleUpdateHandler(null, getSsl().getBundle(), customizer); - getSsl().getServerNameBundles() - .forEach((serverNameSslBundle) -> addBundleUpdateHandler(serverNameSslBundle.serverName(), - serverNameSslBundle.bundle(), customizer)); - } - - private void addBundleUpdateHandler(String serverName, String sslBundleName, SslConnectorCustomizer customizer) { - if (StringUtils.hasText(sslBundleName)) { - getSslBundles().addBundleUpdateHandler(sslBundleName, - (sslBundle) -> customizer.update(serverName, sslBundle)); - } - } - /** * Configure the Tomcat {@link Context}. * @param context the Tomcat context * @param initializers initializers to apply */ - protected void configureContext(Context context, ServletContextInitializer[] initializers) { + protected void configureContext(Context context, Iterable initializers) { TomcatStarter starter = new TomcatStarter(initializers); if (context instanceof TomcatEmbeddedContext embeddedContext) { embeddedContext.setStarter(starter); embeddedContext.setFailCtxIfServletStartFails(true); } context.addServletContainerInitializer(starter, NO_CLASSES); - for (LifecycleListener lifecycleListener : this.contextLifecycleListeners) { + for (LifecycleListener lifecycleListener : this.getContextLifecycleListeners()) { context.addLifecycleListener(lifecycleListener); } - for (Valve valve : this.contextValves) { + for (Valve valve : this.getContextValves()) { context.getPipeline().addValve(valve); } for (ErrorPage errorPage : getErrorPages()) { @@ -424,10 +309,10 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto configureSession(context); configureCookieProcessor(context); new DisableReferenceClearingContextCustomizer().customize(context); - for (String webListenerClassName : getWebListenerClassNames()) { + for (String webListenerClassName : getSettings().getWebListenerClassNames()) { context.addApplicationListener(webListenerClassName); } - for (TomcatContextCustomizer customizer : this.tomcatContextCustomizers) { + for (TomcatContextCustomizer customizer : this.getContextCustomizers()) { customizer.customize(context); } } @@ -435,11 +320,11 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto private void configureSession(Context context) { long sessionTimeout = getSessionTimeoutInMinutes(); context.setSessionTimeout((int) sessionTimeout); - Boolean httpOnly = getSession().getCookie().getHttpOnly(); + Boolean httpOnly = this.settings.getSession().getCookie().getHttpOnly(); if (httpOnly != null) { context.setUseHttpOnly(httpOnly); } - if (getSession().isPersistent()) { + if (this.settings.getSession().isPersistent()) { Manager manager = context.getManager(); if (manager == null) { manager = new StandardManager(); @@ -453,24 +338,25 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto } private void setMimeMappings(Context context) { + MimeMappings mimeMappings = this.settings.getMimeMappings(); if (context instanceof TomcatEmbeddedContext embeddedContext) { - embeddedContext.setMimeMappings(getMimeMappings()); + embeddedContext.setMimeMappings(mimeMappings); return; } - for (MimeMappings.Mapping mapping : getMimeMappings()) { + for (MimeMappings.Mapping mapping : mimeMappings) { context.addMimeMapping(mapping.getExtension(), mapping.getMimeType()); } } private void configureCookieProcessor(Context context) { - SameSite sessionSameSite = getSession().getCookie().getSameSite(); + SameSite sessionSameSite = this.settings.getSession().getCookie().getSameSite(); List suppliers = new ArrayList<>(); if (sessionSameSite != null) { suppliers.add(CookieSameSiteSupplier.of(sessionSameSite) .whenHasName(() -> SessionConfig.getSessionCookieName(context))); } - if (!CollectionUtils.isEmpty(getCookieSameSiteSuppliers())) { - suppliers.addAll(getCookieSameSiteSuppliers()); + if (!CollectionUtils.isEmpty(this.settings.getCookieSameSiteSuppliers())) { + suppliers.addAll(this.settings.getCookieSameSiteSuppliers()); } if (!suppliers.isEmpty()) { context.setCookieProcessor(new SuppliedSameSiteCookieProcessor(suppliers)); @@ -480,13 +366,13 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto private void configurePersistSession(Manager manager) { Assert.state(manager instanceof StandardManager, () -> "Unable to persist HTTP session state using manager type " + manager.getClass().getName()); - File dir = getValidSessionStoreDir(); + File dir = this.settings.getSession().getSessionStoreDirectory().getValidDirectory(true); File file = new File(dir, "SESSIONS.ser"); ((StandardManager) manager).setPathname(file.getAbsolutePath()); } private long getSessionTimeoutInMinutes() { - Duration sessionTimeout = getSession().getTimeout(); + Duration sessionTimeout = this.settings.getSession().getTimeout(); if (isZeroOrLess(sessionTimeout)) { return 0; } @@ -522,11 +408,6 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto this.resourceLoader = resourceLoader; } - @Override - public void setBaseDirectory(File baseDirectory) { - this.baseDirectory = baseDirectory; - } - /** * Returns a mutable set of the patterns that match jars to ignore for TLD scanning. * @return the set of jars to ignore for TLD scanning @@ -555,239 +436,9 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto this.tldSkipPatterns.addAll(Arrays.asList(patterns)); } - /** - * The Tomcat protocol to use when create the {@link Connector}. - * @param protocol the protocol - * @see Connector#Connector(String) - */ - public void setProtocol(String protocol) { - Assert.hasLength(protocol, "'protocol' must not be empty"); - this.protocol = protocol; - } - - /** - * Set {@link Valve}s that should be applied to the Tomcat {@link Engine}. Calling - * this method will replace any existing valves. - * @param engineValves the valves to set - */ - public void setEngineValves(Collection engineValves) { - Assert.notNull(engineValves, "'engineValves' must not be null"); - this.engineValves = new ArrayList<>(engineValves); - } - - /** - * Returns a mutable collection of the {@link Valve}s that will be applied to the - * Tomcat {@link Engine}. - * @return the engine valves that will be applied - */ - public Collection getEngineValves() { - return this.engineValves; - } - @Override - public void addEngineValves(Valve... engineValves) { - Assert.notNull(engineValves, "'engineValves' must not be null"); - this.engineValves.addAll(Arrays.asList(engineValves)); - } - - /** - * Set {@link Valve}s that should be applied to the Tomcat {@link Context}. Calling - * this method will replace any existing valves. - * @param contextValves the valves to set - */ - public void setContextValves(Collection contextValves) { - Assert.notNull(contextValves, "'contextValves' must not be null"); - this.contextValves = new ArrayList<>(contextValves); - } - - /** - * Returns a mutable collection of the {@link Valve}s that will be applied to the - * Tomcat {@link Context}. - * @return the context valves that will be applied - * @see #getEngineValves() - */ - public Collection getContextValves() { - return this.contextValves; - } - - /** - * Add {@link Valve}s that should be applied to the Tomcat {@link Context}. - * @param contextValves the valves to add - */ - public void addContextValves(Valve... contextValves) { - Assert.notNull(contextValves, "'contextValves' must not be null"); - this.contextValves.addAll(Arrays.asList(contextValves)); - } - - /** - * Set {@link LifecycleListener}s that should be applied to the Tomcat - * {@link Context}. Calling this method will replace any existing listeners. - * @param contextLifecycleListeners the listeners to set - */ - public void setContextLifecycleListeners(Collection contextLifecycleListeners) { - Assert.notNull(contextLifecycleListeners, "'contextLifecycleListeners' must not be null"); - this.contextLifecycleListeners = new ArrayList<>(contextLifecycleListeners); - } - - /** - * Returns a mutable collection of the {@link LifecycleListener}s that will be applied - * to the Tomcat {@link Context}. - * @return the context lifecycle listeners that will be applied - */ - public Collection getContextLifecycleListeners() { - return this.contextLifecycleListeners; - } - - /** - * Add {@link LifecycleListener}s that should be added to the Tomcat {@link Context}. - * @param contextLifecycleListeners the listeners to add - */ - public void addContextLifecycleListeners(LifecycleListener... contextLifecycleListeners) { - Assert.notNull(contextLifecycleListeners, "'contextLifecycleListeners' must not be null"); - this.contextLifecycleListeners.addAll(Arrays.asList(contextLifecycleListeners)); - } - - /** - * Set {@link TomcatContextCustomizer}s that should be applied to the Tomcat - * {@link Context}. Calling this method will replace any existing customizers. - * @param tomcatContextCustomizers the customizers to set - */ - public void setTomcatContextCustomizers(Collection tomcatContextCustomizers) { - Assert.notNull(tomcatContextCustomizers, "'tomcatContextCustomizers' must not be null"); - this.tomcatContextCustomizers = new LinkedHashSet<>(tomcatContextCustomizers); - } - - /** - * Returns a mutable collection of the {@link TomcatContextCustomizer}s that will be - * applied to the Tomcat {@link Context}. - * @return the listeners that will be applied - */ - public Collection getTomcatContextCustomizers() { - return this.tomcatContextCustomizers; - } - - @Override - public void addContextCustomizers(TomcatContextCustomizer... tomcatContextCustomizers) { - Assert.notNull(tomcatContextCustomizers, "'tomcatContextCustomizers' must not be null"); - this.tomcatContextCustomizers.addAll(Arrays.asList(tomcatContextCustomizers)); - } - - /** - * Set {@link TomcatConnectorCustomizer}s that should be applied to the Tomcat - * {@link Connector}. Calling this method will replace any existing customizers. - * @param tomcatConnectorCustomizers the customizers to set - */ - public void setTomcatConnectorCustomizers( - Collection tomcatConnectorCustomizers) { - Assert.notNull(tomcatConnectorCustomizers, "'tomcatConnectorCustomizers' must not be null"); - this.tomcatConnectorCustomizers = new LinkedHashSet<>(tomcatConnectorCustomizers); - } - - @Override - public void addConnectorCustomizers(TomcatConnectorCustomizer... tomcatConnectorCustomizers) { - Assert.notNull(tomcatConnectorCustomizers, "'tomcatConnectorCustomizers' must not be null"); - this.tomcatConnectorCustomizers.addAll(Arrays.asList(tomcatConnectorCustomizers)); - } - - /** - * Returns a mutable collection of the {@link TomcatConnectorCustomizer}s that will be - * applied to the Tomcat {@link Connector}. - * @return the customizers that will be applied - */ - public Collection getTomcatConnectorCustomizers() { - return this.tomcatConnectorCustomizers; - } - - /** - * Set {@link TomcatProtocolHandlerCustomizer}s that should be applied to the Tomcat - * {@link Connector}. Calling this method will replace any existing customizers. - * @param tomcatProtocolHandlerCustomizer the customizers to set - * @since 2.2.0 - */ - public void setTomcatProtocolHandlerCustomizers( - Collection> tomcatProtocolHandlerCustomizer) { - Assert.notNull(tomcatProtocolHandlerCustomizer, "'tomcatProtocolHandlerCustomizer' must not be null"); - this.tomcatProtocolHandlerCustomizers = new LinkedHashSet<>(tomcatProtocolHandlerCustomizer); - } - - /** - * Add {@link TomcatProtocolHandlerCustomizer}s that should be added to the Tomcat - * {@link Connector}. - * @param tomcatProtocolHandlerCustomizers the customizers to add - * @since 2.2.0 - */ - @Override - public void addProtocolHandlerCustomizers(TomcatProtocolHandlerCustomizer... tomcatProtocolHandlerCustomizers) { - Assert.notNull(tomcatProtocolHandlerCustomizers, "'tomcatProtocolHandlerCustomizers' must not be null"); - this.tomcatProtocolHandlerCustomizers.addAll(Arrays.asList(tomcatProtocolHandlerCustomizers)); - } - - /** - * Returns a mutable collection of the {@link TomcatProtocolHandlerCustomizer}s that - * will be applied to the Tomcat {@link Connector}. - * @return the customizers that will be applied - * @since 2.2.0 - */ - public Collection> getTomcatProtocolHandlerCustomizers() { - return this.tomcatProtocolHandlerCustomizers; - } - - /** - * Add {@link Connector}s in addition to the default connector, e.g. for SSL or AJP. - *

- * {@link #getTomcatConnectorCustomizers Connector customizers} are not applied to - * connectors added this way. - * @param connectors the connectors to add - */ - public void addAdditionalTomcatConnectors(Connector... connectors) { - Assert.notNull(connectors, "'connectors' must not be null"); - this.additionalTomcatConnectors.addAll(Arrays.asList(connectors)); - } - - /** - * Returns a mutable collection of the {@link Connector}s that will be added to the - * Tomcat. - * @return the additionalTomcatConnectors - */ - public List getAdditionalTomcatConnectors() { - return this.additionalTomcatConnectors; - } - - @Override - public void setUriEncoding(Charset uriEncoding) { - this.uriEncoding = uriEncoding; - } - - /** - * Returns the character encoding to use for URL decoding. - * @return the URI encoding - */ - public Charset getUriEncoding() { - return this.uriEncoding; - } - - @Override - public void setBackgroundProcessorDelay(int delay) { - this.backgroundProcessorDelay = delay; - } - - /** - * Set whether the factory should disable Tomcat's MBean registry prior to creating - * the server. - * @param disableMBeanRegistry whether to disable the MBean registry - * @since 2.2.0 - */ - public void setDisableMBeanRegistry(boolean disableMBeanRegistry) { - this.disableMBeanRegistry = disableMBeanRegistry; - } - - /** - * Whether to use APR. - * @param useApr whether to use APR - * @since 3.4.4 - */ - public void setUseApr(boolean useApr) { - this.useApr = useApr; + public ServletWebServerSettings getSettings() { + return this.settings; } /** @@ -825,7 +476,7 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto @Override public void lifecycleEvent(LifecycleEvent event) { if (event.getType().equals(Lifecycle.BEFORE_INIT_EVENT)) { - addResourceJars(getUrlsOfJarsWithMetaInfResources()); + addResourceJars(TomcatServletWebServerFactory.this.getSettings().getStaticResourceUrls()); } } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/tomcat/package-info.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/tomcat/package-info.java new file mode 100644 index 0000000000..d611e0a7b4 --- /dev/null +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/tomcat/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Servlet web server implementation backed by Tomcat. + */ +package org.springframework.boot.web.server.servlet.tomcat; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/CompositeResourceManager.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/undertow/CompositeResourceManager.java similarity index 94% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/CompositeResourceManager.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/undertow/CompositeResourceManager.java index 0d7d4715c6..efe0acc461 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/CompositeResourceManager.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/undertow/CompositeResourceManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.undertow; +package org.springframework.boot.web.server.servlet.undertow; import java.io.IOException; import java.util.Arrays; 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/server/servlet/undertow/DeploymentManagerHttpHandlerFactory.java similarity index 92% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/DeploymentManagerHttpHandlerFactory.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/undertow/DeploymentManagerHttpHandlerFactory.java index 63969ecf11..093a967b66 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/server/servlet/undertow/DeploymentManagerHttpHandlerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.undertow; +package org.springframework.boot.web.server.servlet.undertow; import java.io.Closeable; import java.io.IOException; @@ -24,6 +24,7 @@ import io.undertow.server.HttpServerExchange; import io.undertow.servlet.api.DeploymentManager; import jakarta.servlet.ServletException; +import org.springframework.boot.web.server.undertow.HttpHandlerFactory; import org.springframework.util.Assert; /** diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/FileSessionPersistence.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/undertow/FileSessionPersistence.java similarity index 97% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/FileSessionPersistence.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/undertow/FileSessionPersistence.java index 82f83ff1cd..65df58dc02 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/FileSessionPersistence.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/undertow/FileSessionPersistence.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.undertow; +package org.springframework.boot.web.server.servlet.undertow; import java.io.File; import java.io.FileInputStream; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/JarResourceManager.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/undertow/JarResourceManager.java similarity index 95% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/JarResourceManager.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/undertow/JarResourceManager.java index fd7424ea8c..a95b1dd4f8 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/JarResourceManager.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/undertow/JarResourceManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.undertow; +package org.springframework.boot.web.server.servlet.undertow; import java.io.File; import java.io.IOException; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowDeploymentInfoCustomizer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/undertow/UndertowDeploymentInfoCustomizer.java similarity index 88% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowDeploymentInfoCustomizer.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/undertow/UndertowDeploymentInfoCustomizer.java index 8be9bdd74a..6034e4b743 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowDeploymentInfoCustomizer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/undertow/UndertowDeploymentInfoCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.undertow; +package org.springframework.boot.web.server.servlet.undertow; import io.undertow.servlet.api.DeploymentInfo; @@ -22,7 +22,7 @@ import io.undertow.servlet.api.DeploymentInfo; * Callback interface that can be used to customize an Undertow {@link DeploymentInfo}. * * @author Phillip Webb - * @since 2.0.0 + * @since 4.0.0 * @see UndertowServletWebServerFactory */ @FunctionalInterface diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowServletWebServer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/undertow/UndertowServletWebServer.java similarity index 87% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowServletWebServer.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/undertow/UndertowServletWebServer.java index 56ffd9416a..880002c28f 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowServletWebServer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/undertow/UndertowServletWebServer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.undertow; +package org.springframework.boot.web.server.servlet.undertow; import io.undertow.Handlers; import io.undertow.Undertow.Builder; @@ -22,6 +22,8 @@ import io.undertow.server.HttpHandler; import io.undertow.servlet.api.DeploymentManager; import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.undertow.HttpHandlerFactory; +import org.springframework.boot.web.server.undertow.UndertowWebServer; import org.springframework.util.StringUtils; /** @@ -34,7 +36,7 @@ import org.springframework.util.StringUtils; * @author Eddú Meléndez * @author Christoph Dreis * @author Kristine Jetzke - * @since 2.0.0 + * @since 4.0.0 * @see UndertowServletWebServerFactory */ public class UndertowServletWebServer extends UndertowWebServer { @@ -49,7 +51,7 @@ public class UndertowServletWebServer extends UndertowWebServer { * @param httpHandlerFactories the handler factories * @param contextPath the root context path * @param autoStart if the server should be started - * @since 2.3.0 + * @since 4.0.0 */ public UndertowServletWebServer(Builder builder, Iterable httpHandlerFactories, String contextPath, boolean autoStart) { @@ -77,9 +79,9 @@ public class UndertowServletWebServer extends UndertowWebServer { } @Override - protected String getStartLogMessage() { + protected String getStartedLogMessage() { String contextPath = StringUtils.hasText(this.contextPath) ? this.contextPath : "/"; - StringBuilder message = new StringBuilder(super.getStartLogMessage()); + StringBuilder message = new StringBuilder(super.getStartedLogMessage()); message.append(" with context path '"); message.append(contextPath); message.append("'"); diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowServletWebServerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/undertow/UndertowServletWebServerFactory.java similarity index 82% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowServletWebServerFactory.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/undertow/UndertowServletWebServerFactory.java index a62f79947d..a2d28079bc 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowServletWebServerFactory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/undertow/UndertowServletWebServerFactory.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.undertow; +package org.springframework.boot.web.server.servlet.undertow; import java.io.File; import java.io.IOException; @@ -59,16 +59,24 @@ import io.undertow.servlet.util.ImmediateInstanceFactory; import jakarta.servlet.ServletContainerInitializer; import jakarta.servlet.ServletContext; import jakarta.servlet.ServletException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.boot.web.server.Cookie.SameSite; import org.springframework.boot.web.server.ErrorPage; import org.springframework.boot.web.server.MimeMappings.Mapping; import org.springframework.boot.web.server.WebServer; -import org.springframework.boot.web.servlet.ServletContextInitializer; -import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactory; -import org.springframework.boot.web.servlet.server.CookieSameSiteSupplier; -import org.springframework.boot.web.servlet.server.ServletWebServerFactory; +import org.springframework.boot.web.server.servlet.ConfigurableServletWebServerFactory; +import org.springframework.boot.web.server.servlet.ContextPath; +import org.springframework.boot.web.server.servlet.CookieSameSiteSupplier; +import org.springframework.boot.web.server.servlet.DocumentRoot; +import org.springframework.boot.web.server.servlet.ServletContextInitializer; +import org.springframework.boot.web.server.servlet.ServletContextInitializers; +import org.springframework.boot.web.server.servlet.ServletWebServerFactory; +import org.springframework.boot.web.server.servlet.ServletWebServerSettings; +import org.springframework.boot.web.server.undertow.HttpHandlerFactory; +import org.springframework.boot.web.server.undertow.UndertowWebServerFactory; import org.springframework.context.ResourceLoaderAware; import org.springframework.core.io.ResourceLoader; import org.springframework.util.Assert; @@ -86,17 +94,19 @@ import org.springframework.util.CollectionUtils; * @author Marcos Barbero * @author Eddú Meléndez * @author Scott Frederick - * @since 2.0.0 + * @since 4.0.0 * @see UndertowServletWebServer */ -public class UndertowServletWebServerFactory extends AbstractServletWebServerFactory - implements ConfigurableUndertowWebServerFactory, ResourceLoaderAware { +public class UndertowServletWebServerFactory extends UndertowWebServerFactory + implements ConfigurableServletWebServerFactory, ResourceLoaderAware { + + private static final Log logger = LogFactory.getLog(UndertowServletWebServerFactory.class); private static final Pattern ENCODED_SLASH = Pattern.compile("%2F", Pattern.LITERAL); private static final Set> NO_CLASSES = Collections.emptySet(); - private final UndertowWebServerFactoryDelegate delegate = new UndertowWebServerFactoryDelegate(); + private final ServletWebServerSettings settings = new ServletWebServerSettings(); private Set deploymentInfoCustomizers = new LinkedHashSet<>(); @@ -110,7 +120,7 @@ public class UndertowServletWebServerFactory extends AbstractServletWebServerFac * Create a new {@link UndertowServletWebServerFactory} instance. */ public UndertowServletWebServerFactory() { - getJsp().setRegistered(false); + getSettings().getJsp().setRegistered(false); } /** @@ -120,7 +130,7 @@ public class UndertowServletWebServerFactory extends AbstractServletWebServerFac */ public UndertowServletWebServerFactory(int port) { super(port); - getJsp().setRegistered(false); + getSettings().getJsp().setRegistered(false); } /** @@ -130,94 +140,18 @@ public class UndertowServletWebServerFactory extends AbstractServletWebServerFac * @param port the port to listen on */ public UndertowServletWebServerFactory(String contextPath, int port) { - super(contextPath, port); - getJsp().setRegistered(false); - } - - @Override - public void setBuilderCustomizers(Collection customizers) { - this.delegate.setBuilderCustomizers(customizers); - } - - @Override - public void addBuilderCustomizers(UndertowBuilderCustomizer... customizers) { - this.delegate.addBuilderCustomizers(customizers); + super(port); + getSettings().setContextPath(ContextPath.of(contextPath)); + getSettings().getJsp().setRegistered(false); } /** - * Returns a mutable collection of the {@link UndertowBuilderCustomizer}s that will be - * applied to the Undertow {@link Builder}. + * Returns a mutable collection of the {@link UndertowDeploymentInfoCustomizer}s that + * will be applied to the Undertow {@link DeploymentInfo}. * @return the customizers that will be applied */ - public Collection getBuilderCustomizers() { - return this.delegate.getBuilderCustomizers(); - } - - @Override - public void setBufferSize(Integer bufferSize) { - this.delegate.setBufferSize(bufferSize); - } - - @Override - public void setIoThreads(Integer ioThreads) { - this.delegate.setIoThreads(ioThreads); - } - - @Override - public void setWorkerThreads(Integer workerThreads) { - this.delegate.setWorkerThreads(workerThreads); - } - - @Override - public void setUseDirectBuffers(Boolean directBuffers) { - this.delegate.setUseDirectBuffers(directBuffers); - } - - @Override - public void setAccessLogDirectory(File accessLogDirectory) { - this.delegate.setAccessLogDirectory(accessLogDirectory); - } - - @Override - public void setAccessLogPattern(String accessLogPattern) { - this.delegate.setAccessLogPattern(accessLogPattern); - } - - @Override - public void setAccessLogPrefix(String accessLogPrefix) { - this.delegate.setAccessLogPrefix(accessLogPrefix); - } - - public String getAccessLogPrefix() { - return this.delegate.getAccessLogPrefix(); - } - - @Override - public void setAccessLogSuffix(String accessLogSuffix) { - this.delegate.setAccessLogSuffix(accessLogSuffix); - } - - @Override - public void setAccessLogEnabled(boolean accessLogEnabled) { - this.delegate.setAccessLogEnabled(accessLogEnabled); - } - - public boolean isAccessLogEnabled() { - return this.delegate.isAccessLogEnabled(); - } - - @Override - public void setAccessLogRotate(boolean accessLogRotate) { - this.delegate.setAccessLogRotate(accessLogRotate); - } - - @Override - public void setUseForwardHeaders(boolean useForwardHeaders) { - this.delegate.setUseForwardHeaders(useForwardHeaders); - } - - protected final boolean isUseForwardHeaders() { - return this.delegate.isUseForwardHeaders(); + public Collection getDeploymentInfoCustomizers() { + return this.deploymentInfoCustomizers; } /** @@ -241,15 +175,6 @@ public class UndertowServletWebServerFactory extends AbstractServletWebServerFac this.deploymentInfoCustomizers.addAll(Arrays.asList(customizers)); } - /** - * Returns a mutable collection of the {@link UndertowDeploymentInfoCustomizer}s that - * will be applied to the Undertow {@link DeploymentInfo}. - * @return the customizers that will be applied - */ - public Collection getDeploymentInfoCustomizers() { - return this.deploymentInfoCustomizers; - } - @Override public void setResourceLoader(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; @@ -258,7 +183,6 @@ public class UndertowServletWebServerFactory extends AbstractServletWebServerFac /** * Return if filters should be eagerly initialized. * @return {@code true} if filters are eagerly initialized, otherwise {@code false}. - * @since 2.4.0 */ public boolean isEagerFilterInit() { return this.eagerFilterInit; @@ -268,7 +192,6 @@ public class UndertowServletWebServerFactory extends AbstractServletWebServerFac * Set whether filters should be eagerly initialized. * @param eagerFilterInit {@code true} if filters are eagerly initialized, otherwise * {@code false}. - * @since 2.4.0 */ public void setEagerFilterInit(boolean eagerFilterInit) { this.eagerFilterInit = eagerFilterInit; @@ -278,7 +201,6 @@ public class UndertowServletWebServerFactory extends AbstractServletWebServerFac * Return whether the request path should be preserved on forward. * @return {@code true} if the path should be preserved when a request is forwarded, * otherwise {@code false}. - * @since 2.4.0 */ public boolean isPreservePathOnForward() { return this.preservePathOnForward; @@ -288,7 +210,6 @@ public class UndertowServletWebServerFactory extends AbstractServletWebServerFac * Set whether the request path should be preserved on forward. * @param preservePathOnForward {@code true} if the path should be preserved when a * request is forwarded, otherwise {@code false}. - * @since 2.4.0 */ public void setPreservePathOnForward(boolean preservePathOnForward) { this.preservePathOnForward = preservePathOnForward; @@ -296,7 +217,7 @@ public class UndertowServletWebServerFactory extends AbstractServletWebServerFac @Override public WebServer getWebServer(ServletContextInitializer... initializers) { - Builder builder = this.delegate.createBuilder(this, this::getSslBundle, this::getServerNameSslBundles); + Builder builder = createBuilder(this, this::getSslBundle, this::getServerNameSslBundles); DeploymentManager manager = createManager(initializers); return getUndertowWebServer(builder, manager, getPort()); } @@ -305,10 +226,10 @@ public class UndertowServletWebServerFactory extends AbstractServletWebServerFac DeploymentInfo deployment = Servlets.deployment(); registerServletContainerInitializerToDriveServletContextInitializers(deployment, initializers); deployment.setClassLoader(getServletClassLoader()); - deployment.setContextPath(getContextPath()); - deployment.setDisplayName(getDisplayName()); + deployment.setContextPath(getSettings().getContextPath().toString()); + deployment.setDisplayName(getSettings().getDisplayName()); deployment.setDeploymentName("spring-boot"); - if (isRegisterDefaultServlet()) { + if (getSettings().isRegisterDefaultServlet()) { deployment.addServlet(Servlets.servlet("default", DefaultServlet.class)); } configureErrorPages(deployment); @@ -322,8 +243,8 @@ public class UndertowServletWebServerFactory extends AbstractServletWebServerFac for (UndertowDeploymentInfoCustomizer customizer : this.deploymentInfoCustomizers) { customizer.customize(deployment); } - if (getSession().isPersistent()) { - File dir = getValidSessionStoreDir(); + if (getSettings().getSession().isPersistent()) { + File dir = getSettings().getSession().getSessionStoreDirectory().getValidDirectory(true); deployment.setSessionPersistenceManager(new FileSessionPersistence(dir)); } addLocaleMappings(deployment); @@ -333,14 +254,14 @@ public class UndertowServletWebServerFactory extends AbstractServletWebServerFac removeSuperfluousMimeMappings(managerDeployment, deployment); } SessionManager sessionManager = manager.getDeployment().getSessionManager(); - Duration timeoutDuration = getSession().getTimeout(); + Duration timeoutDuration = getSettings().getSession().getTimeout(); int sessionTimeout = (isZeroOrLess(timeoutDuration) ? -1 : (int) timeoutDuration.getSeconds()); sessionManager.setDefaultSessionTimeout(sessionTimeout); return manager; } private void configureWebListeners(DeploymentInfo deployment) { - for (String className : getWebListenerClassNames()) { + for (String className : getSettings().getWebListenerClassNames()) { try { deployment.addListener(new ListenerInfo(loadWebListenerClass(className))); } @@ -360,13 +281,13 @@ public class UndertowServletWebServerFactory extends AbstractServletWebServerFac } private void addLocaleMappings(DeploymentInfo deployment) { - getLocaleCharsetMappings() + getSettings().getLocaleCharsetMappings() .forEach((locale, charset) -> deployment.addLocaleCharsetMapping(locale.toString(), charset.toString())); } private void registerServletContainerInitializerToDriveServletContextInitializers(DeploymentInfo deployment, ServletContextInitializer... initializers) { - ServletContextInitializer[] mergedInitializers = mergeInitializers(initializers); + ServletContextInitializers mergedInitializers = ServletContextInitializers.from(this.settings, initializers); Initializer initializer = new Initializer(mergedInitializers); deployment.addServletContainerInitializer(new ServletContainerInitializerInfo(Initializer.class, new ImmediateInstanceFactory<>(initializer), NO_CLASSES)); @@ -380,9 +301,11 @@ public class UndertowServletWebServerFactory extends AbstractServletWebServerFac } private ResourceManager getDocumentRootResourceManager() { - File root = getValidDocumentRoot(); + DocumentRoot documentRoot = new DocumentRoot(logger); + documentRoot.setDirectory(this.settings.getDocumentRoot()); + File root = documentRoot.getValidDirectory(); File docBase = getCanonicalDocumentRoot(root); - List metaInfResourceUrls = getUrlsOfJarsWithMetaInfResources(); + List metaInfResourceUrls = getSettings().getStaticResourceUrls(); List resourceJarUrls = new ArrayList<>(); List managers = new ArrayList<>(); ResourceManager rootManager = (docBase.isDirectory() ? new FileResourceManager(docBase, 0) @@ -441,7 +364,7 @@ public class UndertowServletWebServerFactory extends AbstractServletWebServerFac } private void configureMimeMappings(DeploymentInfo deployment) { - for (Mapping mimeMapping : getMimeMappings()) { + for (Mapping mimeMapping : getSettings().getMimeMappings()) { deployment.addMimeMapping(new MimeMapping(mimeMapping.getExtension(), mimeMapping.getMimeType())); } } @@ -473,33 +396,39 @@ public class UndertowServletWebServerFactory extends AbstractServletWebServerFac if (cooHandlerFactory != null) { initialHandlerFactories.add(cooHandlerFactory); } - List httpHandlerFactories = this.delegate.createHttpHandlerFactories(this, + List httpHandlerFactories = createHttpHandlerFactories(this, initialHandlerFactories.toArray(new HttpHandlerFactory[0])); - return new UndertowServletWebServer(builder, httpHandlerFactories, getContextPath(), port >= 0); + return new UndertowServletWebServer(builder, httpHandlerFactories, getSettings().getContextPath().toString(), + port >= 0); } private HttpHandlerFactory getCookieHandlerFactory(Deployment deployment) { - SameSite sessionSameSite = getSession().getCookie().getSameSite(); + SameSite sessionSameSite = getSettings().getSession().getCookie().getSameSite(); List suppliers = new ArrayList<>(); if (sessionSameSite != null) { String sessionCookieName = deployment.getServletContext().getSessionCookieConfig().getName(); suppliers.add(CookieSameSiteSupplier.of(sessionSameSite).whenHasName(sessionCookieName)); } - if (!CollectionUtils.isEmpty(getCookieSameSiteSuppliers())) { - suppliers.addAll(getCookieSameSiteSuppliers()); + if (!CollectionUtils.isEmpty(getSettings().getCookieSameSiteSuppliers())) { + suppliers.addAll(getSettings().getCookieSameSiteSuppliers()); } return (!suppliers.isEmpty()) ? (next) -> new SuppliedSameSiteCookieHandler(next, suppliers) : null; } + @Override + public ServletWebServerSettings getSettings() { + return this.settings; + } + /** * {@link ServletContainerInitializer} to initialize {@link ServletContextInitializer * ServletContextInitializers}. */ private static class Initializer implements ServletContainerInitializer { - private final ServletContextInitializer[] initializers; + private final ServletContextInitializers initializers; - Initializer(ServletContextInitializer[] initializers) { + Initializer(ServletContextInitializers initializers) { this.initializers = initializers; } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/undertow/package-info.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/undertow/package-info.java new file mode 100644 index 0000000000..da13c4359b --- /dev/null +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/servlet/undertow/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Servlet web server implementation backed by Undertow. + */ +package org.springframework.boot.web.server.servlet.undertow; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/CompressionConnectorCustomizer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/CompressionConnectorCustomizer.java similarity index 88% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/CompressionConnectorCustomizer.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/CompressionConnectorCustomizer.java index 16f311f0a9..4c28bd9737 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/CompressionConnectorCustomizer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/CompressionConnectorCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.tomcat; +package org.springframework.boot.web.server.tomcat; import org.apache.catalina.connector.Connector; import org.apache.coyote.ProtocolHandler; @@ -28,12 +28,13 @@ import org.springframework.util.StringUtils; * Connector. * * @author Brian Clozel + * @since 4.0.0 */ -class CompressionConnectorCustomizer implements TomcatConnectorCustomizer { +public class CompressionConnectorCustomizer implements TomcatConnectorCustomizer { private final Compression compression; - CompressionConnectorCustomizer(Compression compression) { + public CompressionConnectorCustomizer(Compression compression) { this.compression = compression; } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/ConfigurableTomcatWebServerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/ConfigurableTomcatWebServerFactory.java similarity index 86% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/ConfigurableTomcatWebServerFactory.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/ConfigurableTomcatWebServerFactory.java index 7f4853b2f3..c64a5ddcf6 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/ConfigurableTomcatWebServerFactory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/ConfigurableTomcatWebServerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.tomcat; +package org.springframework.boot.web.server.tomcat; import java.io.File; import java.nio.charset.Charset; @@ -25,12 +25,14 @@ import org.apache.catalina.Valve; import org.apache.catalina.connector.Connector; import org.springframework.boot.web.server.ConfigurableWebServerFactory; +import org.springframework.boot.web.server.reactive.tomcat.TomcatReactiveWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; /** * {@link ConfigurableWebServerFactory} for Tomcat-specific features. * * @author Brian Clozel - * @since 2.0.0 + * @since 4.0.0 * @see TomcatServletWebServerFactory * @see TomcatReactiveWebServerFactory */ @@ -72,7 +74,7 @@ public interface ConfigurableTomcatWebServerFactory extends ConfigurableWebServe * Add {@link TomcatProtocolHandlerCustomizer}s that should be added to the Tomcat * {@link Connector}. * @param tomcatProtocolHandlerCustomizers the customizers to add - * @since 2.2.0 + * @since 4.0.0 */ void addProtocolHandlerCustomizers(TomcatProtocolHandlerCustomizer... tomcatProtocolHandlerCustomizers); @@ -83,4 +85,10 @@ public interface ConfigurableTomcatWebServerFactory extends ConfigurableWebServe */ void setUriEncoding(Charset uriEncoding); + /** + * Whether to use APR. + * @param useApr whether to use APR + */ + void setUseApr(boolean useApr); + } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/ConnectorStartFailedException.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/ConnectorStartFailedException.java similarity index 91% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/ConnectorStartFailedException.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/ConnectorStartFailedException.java index 3a25c3bfe7..729f4567ad 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/ConnectorStartFailedException.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/ConnectorStartFailedException.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.tomcat; +package org.springframework.boot.web.server.tomcat; import org.apache.catalina.connector.Connector; @@ -25,7 +25,7 @@ import org.springframework.boot.web.server.WebServerException; * to start, for example due to a port clash or incorrect SSL configuration. * * @author Andy Wilkinson - * @since 2.0.0 + * @since 4.0.0 */ public class ConnectorStartFailedException extends WebServerException { diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/ConnectorStartFailureAnalyzer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/ConnectorStartFailureAnalyzer.java similarity index 96% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/ConnectorStartFailureAnalyzer.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/ConnectorStartFailureAnalyzer.java index bfe87f9558..cbe6db190d 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/ConnectorStartFailureAnalyzer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/ConnectorStartFailureAnalyzer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.tomcat; +package org.springframework.boot.web.server.tomcat; import org.springframework.boot.diagnostics.AbstractFailureAnalyzer; import org.springframework.boot.diagnostics.FailureAnalysis; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/DisableReferenceClearingContextCustomizer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/DisableReferenceClearingContextCustomizer.java similarity index 89% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/DisableReferenceClearingContextCustomizer.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/DisableReferenceClearingContextCustomizer.java index fe834ba952..c0853071ce 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/DisableReferenceClearingContextCustomizer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/DisableReferenceClearingContextCustomizer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.tomcat; +package org.springframework.boot.web.server.tomcat; import org.apache.catalina.Context; import org.apache.catalina.core.StandardContext; @@ -24,8 +24,9 @@ import org.apache.catalina.core.StandardContext; * to avoid reflective access warnings on Java 9 and later JVMs. * * @author Andy Wilkinson + * @since 4.0.0 */ -class DisableReferenceClearingContextCustomizer implements TomcatContextCustomizer { +public class DisableReferenceClearingContextCustomizer implements TomcatContextCustomizer { @Override public void customize(Context context) { diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/GracefulShutdown.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/GracefulShutdown.java similarity index 98% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/GracefulShutdown.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/GracefulShutdown.java index e9757f8f2a..1df1ff2d2e 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/GracefulShutdown.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/GracefulShutdown.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.tomcat; +package org.springframework.boot.web.server.tomcat; import java.util.ArrayList; import java.util.Collections; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/LazySessionIdGenerator.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/LazySessionIdGenerator.java similarity index 95% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/LazySessionIdGenerator.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/LazySessionIdGenerator.java index 9bdad95b15..9869a506cd 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/LazySessionIdGenerator.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/LazySessionIdGenerator.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.tomcat; +package org.springframework.boot.web.server.tomcat; import org.apache.catalina.LifecycleException; import org.apache.catalina.LifecycleState; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/SslConnectorCustomizer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/SslConnectorCustomizer.java similarity index 93% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/SslConnectorCustomizer.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/SslConnectorCustomizer.java index cadb12d424..590ab15037 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/SslConnectorCustomizer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/SslConnectorCustomizer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.tomcat; +package org.springframework.boot.web.server.tomcat; import java.util.Map; @@ -42,8 +42,9 @@ import org.springframework.util.StringUtils; * @author Scott Frederick * @author Cyril Dangerville * @author Moritz Halbritter + * @since 4.0.0 */ -class SslConnectorCustomizer { +public class SslConnectorCustomizer { private final Log logger; @@ -51,20 +52,20 @@ class SslConnectorCustomizer { private final Connector connector; - SslConnectorCustomizer(Log logger, Connector connector, ClientAuth clientAuth) { + public SslConnectorCustomizer(Log logger, Connector connector, ClientAuth clientAuth) { this.logger = logger; this.clientAuth = clientAuth; this.connector = connector; } - void update(String serverName, SslBundle updatedSslBundle) { + public void update(String serverName, SslBundle updatedSslBundle) { AbstractHttp11Protocol protocol = (AbstractHttp11Protocol) this.connector.getProtocolHandler(); String host = (serverName != null) ? serverName : protocol.getDefaultSSLHostConfigName(); this.logger.debug("SSL Bundle for host " + host + " has been updated, reloading SSL configuration"); addSslHostConfig(protocol, host, updatedSslBundle); } - void customize(SslBundle sslBundle, Map serverNameSslBundles) { + public void customize(SslBundle sslBundle, Map serverNameSslBundles) { ProtocolHandler handler = this.connector.getProtocolHandler(); Assert.state(handler instanceof AbstractHttp11Protocol, "To use SSL, the connector's protocol handler must be an AbstractHttp11Protocol subclass"); diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatConnectorCustomizer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/TomcatConnectorCustomizer.java similarity index 88% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatConnectorCustomizer.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/TomcatConnectorCustomizer.java index 19a5d81f79..b5d6a62a13 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatConnectorCustomizer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/TomcatConnectorCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.tomcat; +package org.springframework.boot.web.server.tomcat; import org.apache.catalina.connector.Connector; @@ -22,7 +22,7 @@ import org.apache.catalina.connector.Connector; * Callback interface that can be used to customize a Tomcat {@link Connector}. * * @author Dave Syer - * @since 2.0.0 + * @since 4.0.0 * @see ConfigurableTomcatWebServerFactory */ @FunctionalInterface diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatContextCustomizer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/TomcatContextCustomizer.java similarity index 81% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatContextCustomizer.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/TomcatContextCustomizer.java index 1ed8c94004..b953df2006 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatContextCustomizer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/TomcatContextCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,15 +14,17 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.tomcat; +package org.springframework.boot.web.server.tomcat; import org.apache.catalina.Context; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; + /** * Callback interface that can be used to customize a Tomcat {@link Context}. * * @author Dave Syer - * @since 2.0.0 + * @since 4.0.0 * @see TomcatServletWebServerFactory */ @FunctionalInterface diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedContext.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/TomcatEmbeddedContext.java similarity index 93% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedContext.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/TomcatEmbeddedContext.java index 77347e0ec0..62c13dd2de 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedContext.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/TomcatEmbeddedContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.tomcat; +package org.springframework.boot.web.server.tomcat; import java.util.ArrayList; import java.util.Arrays; @@ -41,8 +41,9 @@ import org.springframework.util.ClassUtils; * * @author Phillip Webb * @author Andy Wilkinson + * @since 4.0.0 */ -class TomcatEmbeddedContext extends StandardContext { +public class TomcatEmbeddedContext extends StandardContext { private TomcatStarter starter; @@ -114,7 +115,7 @@ class TomcatEmbeddedContext extends StandardContext { } } - void setStarter(TomcatStarter starter) { + public void setStarter(TomcatStarter starter) { this.starter = starter; } @@ -122,7 +123,7 @@ class TomcatEmbeddedContext extends StandardContext { return this.starter; } - void setMimeMappings(MimeMappings mimeMappings) { + public void setMimeMappings(MimeMappings mimeMappings) { this.mimeMappings = mimeMappings; } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedWebappClassLoader.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/TomcatEmbeddedWebappClassLoader.java similarity index 96% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedWebappClassLoader.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/TomcatEmbeddedWebappClassLoader.java index bdd3117b8f..75226c6d09 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedWebappClassLoader.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/TomcatEmbeddedWebappClassLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.tomcat; +package org.springframework.boot.web.server.tomcat; import java.io.IOException; import java.net.URL; @@ -34,7 +34,7 @@ import org.apache.tomcat.util.compat.JreCompat; * * @author Phillip Webb * @author Andy Clement - * @since 2.0.0 + * @since 4.0.0 */ public class TomcatEmbeddedWebappClassLoader extends ParallelWebappClassLoader { diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatProtocolHandlerCustomizer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/TomcatProtocolHandlerCustomizer.java similarity index 90% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatProtocolHandlerCustomizer.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/TomcatProtocolHandlerCustomizer.java index d14b79fb6d..870202f205 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatProtocolHandlerCustomizer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/TomcatProtocolHandlerCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.tomcat; +package org.springframework.boot.web.server.tomcat; import org.apache.catalina.connector.Connector; import org.apache.coyote.ProtocolHandler; @@ -25,7 +25,7 @@ import org.apache.coyote.ProtocolHandler; * * @param specified type for customization based on {@link ProtocolHandler} * @author Pascal Zwick - * @since 2.2.0 + * @since 4.0.0 * @see ConfigurableTomcatWebServerFactory */ @FunctionalInterface diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatStarter.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/TomcatStarter.java similarity index 82% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatStarter.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/TomcatStarter.java index ce79752de6..6bdea21f43 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatStarter.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/TomcatStarter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.tomcat; +package org.springframework.boot.web.server.tomcat; import java.util.Set; @@ -24,7 +24,7 @@ import jakarta.servlet.ServletException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.boot.web.servlet.ServletContextInitializer; +import org.springframework.boot.web.server.servlet.ServletContextInitializer; /** * {@link ServletContainerInitializer} used to trigger {@link ServletContextInitializer @@ -32,16 +32,17 @@ import org.springframework.boot.web.servlet.ServletContextInitializer; * * @author Phillip Webb * @author Andy Wilkinson + * @since 4.0.0 */ -class TomcatStarter implements ServletContainerInitializer { +public class TomcatStarter implements ServletContainerInitializer { private static final Log logger = LogFactory.getLog(TomcatStarter.class); - private final ServletContextInitializer[] initializers; + private final Iterable initializers; private volatile Exception startUpException; - TomcatStarter(ServletContextInitializer[] initializers) { + public TomcatStarter(Iterable initializers) { this.initializers = initializers; } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatWebServer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/TomcatWebServer.java similarity index 98% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatWebServer.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/TomcatWebServer.java index b8e31b083d..7f84cc870a 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatWebServer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/TomcatWebServer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.tomcat; +package org.springframework.boot.web.server.tomcat; import java.util.Arrays; import java.util.HashMap; @@ -45,6 +45,8 @@ 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.server.WebServerException; +import org.springframework.boot.web.server.reactive.tomcat.TomcatReactiveWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -55,7 +57,7 @@ import org.springframework.util.StringUtils; * * @author Brian Clozel * @author Kristine Jetzke - * @since 2.0.0 + * @since 4.0.0 */ public class TomcatWebServer implements WebServer { @@ -97,7 +99,7 @@ public class TomcatWebServer implements WebServer { * @param tomcat the underlying Tomcat server * @param autoStart if the server should be started * @param shutdown type of shutdown supported by the server - * @since 2.3.0 + * @since 4.0.0 */ public TomcatWebServer(Tomcat tomcat, boolean autoStart, Shutdown shutdown) { Assert.notNull(tomcat, "'tomcat' must not be null"); diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatReactiveWebServerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/TomcatWebServerFactory.java similarity index 55% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatReactiveWebServerFactory.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/TomcatWebServerFactory.java index e6afa451fb..cbef76d448 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatReactiveWebServerFactory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/TomcatWebServerFactory.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.tomcat; +package org.springframework.boot.web.server.tomcat; import java.io.File; import java.nio.charset.Charset; @@ -29,48 +29,34 @@ import java.util.Set; import org.apache.catalina.Context; import org.apache.catalina.Engine; import org.apache.catalina.Executor; -import org.apache.catalina.Host; import org.apache.catalina.LifecycleListener; import org.apache.catalina.Valve; import org.apache.catalina.connector.Connector; import org.apache.catalina.core.AprLifecycleListener; -import org.apache.catalina.loader.WebappLoader; import org.apache.catalina.startup.Tomcat; -import org.apache.catalina.startup.Tomcat.FixContextListener; -import org.apache.catalina.webresources.StandardRoot; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.coyote.AbstractProtocol; import org.apache.coyote.ProtocolHandler; import org.apache.coyote.http2.Http2Protocol; import org.apache.tomcat.util.modeler.Registry; -import org.apache.tomcat.util.scan.StandardJarScanFilter; import org.springframework.boot.util.LambdaSafe; -import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactory; -import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; +import org.springframework.boot.web.server.AbstractConfigurableWebServerFactory; import org.springframework.boot.web.server.Ssl; -import org.springframework.boot.web.server.WebServer; -import org.springframework.http.server.reactive.HttpHandler; -import org.springframework.http.server.reactive.TomcatHttpHandlerAdapter; +import org.springframework.core.NativeDetector; import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; /** - * {@link ReactiveWebServerFactory} that can be used to create a {@link TomcatWebServer}. + * Base class for factories that produce a {@link TomcatWebServer}. * - * @author Brian Clozel - * @author HaiTao Zhang - * @author Moritz Halbritter - * @author Scott Frederick - * @since 2.0.0 + * @author Andy Wilkinson + * @since 4.0.0 */ -public class TomcatReactiveWebServerFactory extends AbstractReactiveWebServerFactory +public class TomcatWebServerFactory extends AbstractConfigurableWebServerFactory implements ConfigurableTomcatWebServerFactory { - private static final Log logger = LogFactory.getLog(TomcatReactiveWebServerFactory.class); - private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; /** @@ -78,65 +64,317 @@ public class TomcatReactiveWebServerFactory extends AbstractReactiveWebServerFac */ public static final String DEFAULT_PROTOCOL = "org.apache.coyote.http11.Http11NioProtocol"; + private final Log logger = LogFactory.getLog(getClass()); + private File baseDirectory; - private final List engineValves = new ArrayList<>(); + private int backgroundProcessorDelay; + + private List engineValves = new ArrayList<>(); + + private List contextValves = new ArrayList<>(); private List contextLifecycleListeners = new ArrayList<>(); - private Set tomcatContextCustomizers = new LinkedHashSet<>(); + private Set contextCustomizers = new LinkedHashSet<>(); - private Set tomcatConnectorCustomizers = new LinkedHashSet<>(); + private Set connectorCustomizers = new LinkedHashSet<>(); - private Set> tomcatProtocolHandlerCustomizers = new LinkedHashSet<>(); + private Set> protocolHandlerCustomizers = new LinkedHashSet<>(); - private final List additionalTomcatConnectors = new ArrayList<>(); - - private String protocol = DEFAULT_PROTOCOL; + private List additionalConnectors = new ArrayList<>(); private Charset uriEncoding = DEFAULT_CHARSET; - private int backgroundProcessorDelay; + private String protocol = DEFAULT_PROTOCOL; private boolean disableMBeanRegistry = true; private boolean useApr; - /** - * Create a new {@link TomcatReactiveWebServerFactory} instance. - */ - public TomcatReactiveWebServerFactory() { + protected TomcatWebServerFactory() { } - /** - * Create a new {@link TomcatReactiveWebServerFactory} that listens for requests using - * the specified port. - * @param port the port to listen on - */ - public TomcatReactiveWebServerFactory(int port) { + protected TomcatWebServerFactory(int port) { super(port); } private List getDefaultServerLifecycleListeners() { ArrayList lifecycleListeners = new ArrayList<>(); - if (this.useApr) { + if (this.useApr && !NativeDetector.inNativeImage()) { lifecycleListeners.add(new AprLifecycleListener()); } return lifecycleListeners; } @Override - public WebServer getWebServer(HttpHandler httpHandler) { - if (this.disableMBeanRegistry) { + public void setBaseDirectory(File baseDirectory) { + this.baseDirectory = baseDirectory; + } + + public File getBaseDirectory() { + return this.baseDirectory; + } + + /** + * Returns a mutable collection of the {@link Valve}s that will be applied to the + * Tomcat {@link Engine}. + * @return the engine valves that will be applied + */ + public Collection getEngineValves() { + return this.engineValves; + } + + /** + * Set {@link Valve}s that should be applied to the Tomcat {@link Engine}. Calling + * this method will replace any existing valves. + * @param engineValves the valves to set + */ + public void setEngineValves(Collection engineValves) { + Assert.notNull(engineValves, "'engineValves' must not be null"); + this.engineValves = new ArrayList<>(engineValves); + } + + @Override + public void addEngineValves(Valve... engineValves) { + Assert.notNull(engineValves, "'engineValves' must not be null"); + this.engineValves.addAll(Arrays.asList(engineValves)); + } + + public Charset getUriEncoding() { + return this.uriEncoding; + } + + @Override + public void setUriEncoding(Charset uriEncoding) { + this.uriEncoding = uriEncoding; + } + + public int getBackgroundProcessorDelay() { + return this.backgroundProcessorDelay; + } + + @Override + public void setBackgroundProcessorDelay(int delay) { + this.backgroundProcessorDelay = delay; + } + + public String getProtocol() { + return this.protocol; + } + + /** + * The Tomcat protocol to use when create the {@link Connector}. + * @param protocol the protocol + * @see Connector#Connector(String) + */ + public void setProtocol(String protocol) { + Assert.hasLength(protocol, "'protocol' must not be empty"); + this.protocol = protocol; + } + + /** + * Returns a mutable collection of the {@link Valve}s that will be applied to the + * Tomcat {@link Context}. + * @return the context valves that will be applied + * @see #getEngineValves() + */ + public Collection getContextValves() { + return this.contextValves; + } + + /** + * Set {@link Valve}s that should be applied to the Tomcat {@link Context}. Calling + * this method will replace any existing valves. + * @param contextValves the valves to set + */ + public void setContextValves(Collection contextValves) { + Assert.notNull(contextValves, "'contextValves' must not be null"); + this.contextValves = new ArrayList<>(contextValves); + } + + /** + * Add {@link Valve}s that should be applied to the Tomcat {@link Context}. + * @param contextValves the valves to add + */ + public void addContextValves(Valve... contextValves) { + Assert.notNull(contextValves, "'contextValves' must not be null"); + this.contextValves.addAll(Arrays.asList(contextValves)); + } + + /** + * Returns a mutable collection of the {@link LifecycleListener}s that will be applied + * to the Tomcat {@link Context}. + * @return the context lifecycle listeners that will be applied + */ + public Collection getContextLifecycleListeners() { + return this.contextLifecycleListeners; + } + + /** + * Set {@link LifecycleListener}s that should be applied to the Tomcat + * {@link Context}. Calling this method will replace any existing listeners. + * @param contextLifecycleListeners the listeners to set + */ + public void setContextLifecycleListeners(Collection contextLifecycleListeners) { + Assert.notNull(contextLifecycleListeners, "'contextLifecycleListeners' must not be null"); + this.contextLifecycleListeners = new ArrayList<>(contextLifecycleListeners); + } + + /** + * Add {@link LifecycleListener}s that should be added to the Tomcat {@link Context}. + * @param contextLifecycleListeners the listeners to add + */ + public void addContextLifecycleListeners(LifecycleListener... contextLifecycleListeners) { + Assert.notNull(contextLifecycleListeners, "'contextLifecycleListeners' must not be null"); + this.contextLifecycleListeners.addAll(Arrays.asList(contextLifecycleListeners)); + } + + /** + * Returns a mutable collection of the {@link TomcatContextCustomizer}s that will be + * applied to the Tomcat {@link Context}. + * @return the listeners that will be applied + */ + public Collection getContextCustomizers() { + return this.contextCustomizers; + } + + /** + * Set {@link TomcatContextCustomizer}s that should be applied to the Tomcat + * {@link Context}. Calling this method will replace any existing customizers. + * @param contextCustomizers the customizers to set + */ + public void setContextCustomizers(Collection contextCustomizers) { + Assert.notNull(contextCustomizers, "'contextCustomizers' must not be null"); + this.contextCustomizers = new LinkedHashSet<>(contextCustomizers); + } + + @Override + public void addContextCustomizers(TomcatContextCustomizer... contextCustomizers) { + Assert.notNull(contextCustomizers, "'contextCustomizers' must not be null"); + this.contextCustomizers.addAll(Arrays.asList(contextCustomizers)); + } + + /** + * Returns a mutable collection of the {@link TomcatConnectorCustomizer}s that will be + * applied to the Tomcat {@link Connector}. + * @return the customizers that will be applied + */ + public Set getConnectorCustomizers() { + return this.connectorCustomizers; + } + + /** + * Set {@link TomcatConnectorCustomizer}s that should be applied to the Tomcat + * {@link Connector}. Calling this method will replace any existing customizers. + * @param connectorCustomizers the customizers to set + */ + public void setConnectorCustomizers(Collection connectorCustomizers) { + Assert.notNull(connectorCustomizers, "'connectorCustomizers' must not be null"); + this.connectorCustomizers = new LinkedHashSet<>(connectorCustomizers); + } + + @Override + public void addConnectorCustomizers(TomcatConnectorCustomizer... connectorCustomizers) { + Assert.notNull(connectorCustomizers, "'connectorCustomizers' must not be null"); + this.connectorCustomizers.addAll(Arrays.asList(connectorCustomizers)); + } + + /** + * Returns a mutable collection of the {@link TomcatProtocolHandlerCustomizer}s that + * will be applied to the Tomcat {@link Connector}. + * @return the customizers that will be applied + */ + public Set> getProtocolHandlerCustomizers() { + return this.protocolHandlerCustomizers; + } + + /** + * Set {@link TomcatProtocolHandlerCustomizer}s that should be applied to the Tomcat + * {@link Connector}. Calling this method will replace any existing customizers. + * @param protocolHandlerCustomizers the customizers to set + */ + public void setProtocolHandlerCustomizers( + Collection> protocolHandlerCustomizers) { + Assert.notNull(protocolHandlerCustomizers, "'protocolHandlerCustomizers' must not be null"); + this.protocolHandlerCustomizers = new LinkedHashSet<>(protocolHandlerCustomizers); + } + + @Override + public void addProtocolHandlerCustomizers(TomcatProtocolHandlerCustomizer... protocolHandlerCustomizers) { + Assert.notNull(protocolHandlerCustomizers, "'protocolHandlerCustomizers' must not be null"); + this.protocolHandlerCustomizers.addAll(Arrays.asList(protocolHandlerCustomizers)); + } + + /** + * Returns a mutable collection of the {@link Connector}s that will be added to the + * Tomcat server. + * @return the additional connectors + */ + public List getAdditionalConnectors() { + return this.additionalConnectors; + } + + /** + * Set additional {@link Connector}s that should be added to the Tomcat server . + * Calling this method will replace any existing additional connectors. + * @param additionalConnectors the additionalConnectors to set + */ + public void setAdditionalConnectors(Collection additionalConnectors) { + Assert.notNull(additionalConnectors, "'additionalConnectors' must not be null"); + this.additionalConnectors = new ArrayList<>(additionalConnectors); + } + + /** + * Add {@link Connector}s in addition to the default connector, e.g. for SSL or AJP. + *

+ * {@link #getConnectorCustomizers Connector customizers} are not applied to + * connectors added this way. + * @param connectors the connectors to add + */ + public void addAdditionalConnectors(Connector... connectors) { + Assert.notNull(connectors, "'connectors' must not be null"); + this.additionalConnectors.addAll(Arrays.asList(connectors)); + } + + /** + * Returns whether the factory should disable Tomcat's MBean registry prior to + * creating the server. + * @return whether to disable Tomcat's MBean registry + */ + public boolean isDisableMBeanRegistry() { + return this.disableMBeanRegistry; + } + + /** + * Set whether the factory should disable Tomcat's MBean registry prior to creating + * the server. + * @param disableMBeanRegistry whether to disable the MBean registry + */ + public void setDisableMBeanRegistry(boolean disableMBeanRegistry) { + this.disableMBeanRegistry = disableMBeanRegistry; + } + + /** + * Whether to use APR. + * @param useApr whether to use APR + */ + @Override + public void setUseApr(boolean useApr) { + this.useApr = useApr; + } + + protected Tomcat createTomcat() { + if (this.isDisableMBeanRegistry()) { Registry.disableRegistry(); } Tomcat tomcat = new Tomcat(); - File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat"); + File baseDir = (getBaseDirectory() != null) ? getBaseDirectory() : createTempDir("tomcat"); tomcat.setBaseDir(baseDir.getAbsolutePath()); for (LifecycleListener listener : getDefaultServerLifecycleListeners()) { tomcat.getServer().addLifecycleListener(listener); } - Connector connector = new Connector(this.protocol); + Connector connector = new Connector(getProtocol()); connector.setThrowOnFailure(true); tomcat.getService().addConnector(connector); customizeConnector(connector); @@ -144,64 +382,11 @@ public class TomcatReactiveWebServerFactory extends AbstractReactiveWebServerFac registerConnectorExecutor(tomcat, connector); tomcat.getHost().setAutoDeploy(false); configureEngine(tomcat.getEngine()); - for (Connector additionalConnector : this.additionalTomcatConnectors) { + for (Connector additionalConnector : this.getAdditionalConnectors()) { tomcat.getService().addConnector(additionalConnector); registerConnectorExecutor(tomcat, additionalConnector); } - TomcatHttpHandlerAdapter servlet = new TomcatHttpHandlerAdapter(httpHandler); - prepareContext(tomcat.getHost(), servlet); - return getTomcatWebServer(tomcat); - } - - private void registerConnectorExecutor(Tomcat tomcat, Connector connector) { - if (connector.getProtocolHandler().getExecutor() instanceof Executor executor) { - tomcat.getService().addExecutor(executor); - } - } - - private void configureEngine(Engine engine) { - engine.setBackgroundProcessorDelay(this.backgroundProcessorDelay); - for (Valve valve : this.engineValves) { - engine.getPipeline().addValve(valve); - } - } - - protected void prepareContext(Host host, TomcatHttpHandlerAdapter servlet) { - File docBase = createTempDir("tomcat-docbase"); - TomcatEmbeddedContext context = new TomcatEmbeddedContext(); - StandardRoot resourcesRoot = new StandardRoot(); - resourcesRoot.setReadOnly(true); - context.setResources(resourcesRoot); - context.setPath(""); - context.setDocBase(docBase.getAbsolutePath()); - context.addLifecycleListener(new FixContextListener()); - ClassLoader parentClassLoader = ClassUtils.getDefaultClassLoader(); - context.setParentClassLoader(parentClassLoader); - skipAllTldScanning(context); - WebappLoader loader = new WebappLoader(); - loader.setLoaderInstance(new TomcatEmbeddedWebappClassLoader(parentClassLoader)); - loader.setDelegate(true); - context.setLoader(loader); - Tomcat.addServlet(context, "httpHandlerServlet", servlet).setAsyncSupported(true); - context.addServletMappingDecoded("/", "httpHandlerServlet"); - host.addChild(context); - configureContext(context); - } - - private void skipAllTldScanning(TomcatEmbeddedContext context) { - StandardJarScanFilter filter = new StandardJarScanFilter(); - filter.setTldSkip("*.jar"); - context.getJarScanner().setJarScanFilter(filter); - } - - /** - * Configure the Tomcat {@link Context}. - * @param context the Tomcat context - */ - protected void configureContext(Context context) { - this.contextLifecycleListeners.forEach(context::addLifecycleListener); - new DisableReferenceClearingContextCustomizer().customize(context); - this.tomcatContextCustomizers.forEach((customizer) -> customizer.customize(context)); + return tomcat; } protected void customizeConnector(Connector connector) { @@ -225,26 +410,27 @@ public class TomcatReactiveWebServerFactory extends AbstractReactiveWebServerFac } TomcatConnectorCustomizer compression = new CompressionConnectorCustomizer(getCompression()); compression.customize(connector); - for (TomcatConnectorCustomizer customizer : this.tomcatConnectorCustomizers) { + for (TomcatConnectorCustomizer customizer : this.getConnectorCustomizers()) { customizer.customize(connector); } } - @SuppressWarnings("unchecked") - private void invokeProtocolHandlerCustomizers(ProtocolHandler protocolHandler) { - LambdaSafe - .callbacks(TomcatProtocolHandlerCustomizer.class, this.tomcatProtocolHandlerCustomizers, protocolHandler) - .invoke((customizer) -> customizer.customize(protocolHandler)); - } - private void customizeProtocol(AbstractProtocol protocol) { if (getAddress() != null) { protocol.setAddress(getAddress()); } } + @SuppressWarnings("unchecked") + private void invokeProtocolHandlerCustomizers(ProtocolHandler protocolHandler) { + LambdaSafe + .callbacks(TomcatProtocolHandlerCustomizer.class, this.getProtocolHandlerCustomizers(), protocolHandler) + .invoke((customizer) -> customizer.customize(protocolHandler)); + } + private void customizeSsl(Connector connector) { - SslConnectorCustomizer customizer = new SslConnectorCustomizer(logger, connector, getSsl().getClientAuth()); + SslConnectorCustomizer customizer = new SslConnectorCustomizer(this.logger, connector, + getSsl().getClientAuth()); customizer.customize(getSslBundle(), getServerNameSslBundles()); addBundleUpdateHandler(null, getSsl().getBundle(), customizer); getSsl().getServerNameBundles() @@ -259,233 +445,17 @@ public class TomcatReactiveWebServerFactory extends AbstractReactiveWebServerFac } } - @Override - public void setBaseDirectory(File baseDirectory) { - this.baseDirectory = baseDirectory; + private void registerConnectorExecutor(Tomcat tomcat, Connector connector) { + if (connector.getProtocolHandler().getExecutor() instanceof Executor executor) { + tomcat.getService().addExecutor(executor); + } } - @Override - public void setBackgroundProcessorDelay(int delay) { - this.backgroundProcessorDelay = delay; - } - - /** - * Set {@link TomcatContextCustomizer}s that should be applied to the Tomcat - * {@link Context}. Calling this method will replace any existing customizers. - * @param tomcatContextCustomizers the customizers to set - */ - public void setTomcatContextCustomizers(Collection tomcatContextCustomizers) { - Assert.notNull(tomcatContextCustomizers, "'tomcatContextCustomizers' must not be null"); - this.tomcatContextCustomizers = new LinkedHashSet<>(tomcatContextCustomizers); - } - - /** - * Returns a mutable collection of the {@link TomcatContextCustomizer}s that will be - * applied to the Tomcat {@link Context}. - * @return the listeners that will be applied - */ - public Collection getTomcatContextCustomizers() { - return this.tomcatContextCustomizers; - } - - /** - * Add {@link TomcatContextCustomizer}s that should be added to the Tomcat - * {@link Context}. - * @param tomcatContextCustomizers the customizers to add - */ - @Override - public void addContextCustomizers(TomcatContextCustomizer... tomcatContextCustomizers) { - Assert.notNull(tomcatContextCustomizers, "'tomcatContextCustomizers' must not be null"); - this.tomcatContextCustomizers.addAll(Arrays.asList(tomcatContextCustomizers)); - } - - /** - * Set {@link TomcatConnectorCustomizer}s that should be applied to the Tomcat - * {@link Connector}. Calling this method will replace any existing customizers. - * @param tomcatConnectorCustomizers the customizers to set - */ - public void setTomcatConnectorCustomizers( - Collection tomcatConnectorCustomizers) { - Assert.notNull(tomcatConnectorCustomizers, "'tomcatConnectorCustomizers' must not be null"); - this.tomcatConnectorCustomizers = new LinkedHashSet<>(tomcatConnectorCustomizers); - } - - /** - * Add {@link TomcatConnectorCustomizer}s that should be added to the Tomcat - * {@link Connector}. - * @param tomcatConnectorCustomizers the customizers to add - */ - @Override - public void addConnectorCustomizers(TomcatConnectorCustomizer... tomcatConnectorCustomizers) { - Assert.notNull(tomcatConnectorCustomizers, "'tomcatConnectorCustomizers' must not be null"); - this.tomcatConnectorCustomizers.addAll(Arrays.asList(tomcatConnectorCustomizers)); - } - - /** - * Returns a mutable collection of the {@link TomcatConnectorCustomizer}s that will be - * applied to the Tomcat {@link Connector}. - * @return the customizers that will be applied - */ - public Collection getTomcatConnectorCustomizers() { - return this.tomcatConnectorCustomizers; - } - - /** - * Set {@link TomcatProtocolHandlerCustomizer}s that should be applied to the Tomcat - * {@link Connector}. Calling this method will replace any existing customizers. - * @param tomcatProtocolHandlerCustomizers the customizers to set - * @since 2.2.0 - */ - public void setTomcatProtocolHandlerCustomizers( - Collection> tomcatProtocolHandlerCustomizers) { - Assert.notNull(tomcatProtocolHandlerCustomizers, "'tomcatProtocolHandlerCustomizers' must not be null"); - this.tomcatProtocolHandlerCustomizers = new LinkedHashSet<>(tomcatProtocolHandlerCustomizers); - } - - /** - * Add {@link TomcatProtocolHandlerCustomizer}s that should be added to the Tomcat - * {@link Connector}. - * @param tomcatProtocolHandlerCustomizers the customizers to add - * @since 2.2.0 - */ - @Override - public void addProtocolHandlerCustomizers(TomcatProtocolHandlerCustomizer... tomcatProtocolHandlerCustomizers) { - Assert.notNull(tomcatProtocolHandlerCustomizers, "'tomcatProtocolHandlerCustomizers' must not be null"); - this.tomcatProtocolHandlerCustomizers.addAll(Arrays.asList(tomcatProtocolHandlerCustomizers)); - } - - /** - * Returns a mutable collection of the {@link TomcatProtocolHandlerCustomizer}s that - * will be applied to the Tomcat {@link Connector}. - * @return the customizers that will be applied - * @since 2.2.0 - */ - public Collection> getTomcatProtocolHandlerCustomizers() { - return this.tomcatProtocolHandlerCustomizers; - } - - /** - * Add {@link Connector}s in addition to the default connector, e.g. for SSL or AJP. - *

- * {@link #getTomcatConnectorCustomizers Connector customizers} are not applied to - * connectors added this way. - * @param connectors the connectors to add - * @since 2.2.0 - */ - public void addAdditionalTomcatConnectors(Connector... connectors) { - Assert.notNull(connectors, "'connectors' must not be null"); - this.additionalTomcatConnectors.addAll(Arrays.asList(connectors)); - } - - /** - * Returns a mutable collection of the {@link Connector}s that will be added to the - * Tomcat. - * @return the additionalTomcatConnectors - * @since 2.2.0 - */ - public List getAdditionalTomcatConnectors() { - return this.additionalTomcatConnectors; - } - - @Override - public void addEngineValves(Valve... engineValves) { - Assert.notNull(engineValves, "'engineValves' must not be null"); - this.engineValves.addAll(Arrays.asList(engineValves)); - } - - /** - * Returns a mutable collection of the {@link Valve}s that will be applied to the - * Tomcat {@link Engine}. - * @return the engine valves that will be applied - */ - public List getEngineValves() { - return this.engineValves; - } - - /** - * Set the character encoding to use for URL decoding. If not specified 'UTF-8' will - * be used. - * @param uriEncoding the uri encoding to set - */ - @Override - public void setUriEncoding(Charset uriEncoding) { - this.uriEncoding = uriEncoding; - } - - /** - * Returns the character encoding to use for URL decoding. - * @return the URI encoding - */ - public Charset getUriEncoding() { - return this.uriEncoding; - } - - /** - * Set {@link LifecycleListener}s that should be applied to the Tomcat - * {@link Context}. Calling this method will replace any existing listeners. - * @param contextLifecycleListeners the listeners to set - */ - public void setContextLifecycleListeners(Collection contextLifecycleListeners) { - Assert.notNull(contextLifecycleListeners, "'contextLifecycleListeners' must not be null"); - this.contextLifecycleListeners = new ArrayList<>(contextLifecycleListeners); - } - - /** - * Returns a mutable collection of the {@link LifecycleListener}s that will be applied - * to the Tomcat {@link Context}. - * @return the context lifecycle listeners that will be applied - */ - public Collection getContextLifecycleListeners() { - return this.contextLifecycleListeners; - } - - /** - * Add {@link LifecycleListener}s that should be added to the Tomcat {@link Context}. - * @param contextLifecycleListeners the listeners to add - */ - public void addContextLifecycleListeners(LifecycleListener... contextLifecycleListeners) { - Assert.notNull(contextLifecycleListeners, "'contextLifecycleListeners' must not be null"); - this.contextLifecycleListeners.addAll(Arrays.asList(contextLifecycleListeners)); - } - - /** - * Factory method called to create the {@link TomcatWebServer}. Subclasses can - * override this method to return a different {@link TomcatWebServer} or apply - * additional processing to the Tomcat server. - * @param tomcat the Tomcat server. - * @return a new {@link TomcatWebServer} instance - */ - protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) { - return new TomcatWebServer(tomcat, getPort() >= 0, getShutdown()); - } - - /** - * The Tomcat protocol to use when create the {@link Connector}. - * @param protocol the protocol - * @see Connector#Connector(String) - */ - public void setProtocol(String protocol) { - Assert.hasLength(protocol, "'protocol' must not be empty"); - this.protocol = protocol; - } - - /** - * Set whether the factory should disable Tomcat's MBean registry prior to creating - * the server. - * @param disableMBeanRegistry whether to disable the MBean registry - * @since 2.2.0 - */ - public void setDisableMBeanRegistry(boolean disableMBeanRegistry) { - this.disableMBeanRegistry = disableMBeanRegistry; - } - - /** - * Whether to use APR. - * @param useApr whether to use APR - * @since 3.4.4 - */ - public void setUseApr(boolean useApr) { - this.useApr = useApr; + private void configureEngine(Engine engine) { + engine.setBackgroundProcessorDelay(getBackgroundProcessorDelay()); + for (Valve valve : getEngineValves()) { + engine.getPipeline().addValve(valve); + } } } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/package-info.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/package-info.java similarity index 61% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/package-info.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/package-info.java index f613cb4e05..a8c97e23d5 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/package-info.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/tomcat/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,9 +15,9 @@ */ /** - * Embedded reactive and servlet web server implementations backed by Jetty. + * Reactive and servlet web server implementations backed by Tomcat. * - * @see org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory - * @see org.springframework.boot.web.embedded.jetty.JettyReactiveWebServerFactory + * @see org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory + * @see org.springframework.boot.web.server.reactive.tomcat.TomcatReactiveWebServerFactory */ -package org.springframework.boot.web.embedded.jetty; +package org.springframework.boot.web.server.tomcat; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/AccessLogHttpHandlerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/AccessLogHttpHandlerFactory.java similarity index 98% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/AccessLogHttpHandlerFactory.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/AccessLogHttpHandlerFactory.java index c2520cbbfd..f524787348 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/AccessLogHttpHandlerFactory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/AccessLogHttpHandlerFactory.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.undertow; +package org.springframework.boot.web.server.undertow; import java.io.Closeable; import java.io.File; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/CompressionHttpHandlerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/CompressionHttpHandlerFactory.java similarity index 98% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/CompressionHttpHandlerFactory.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/CompressionHttpHandlerFactory.java index d2311427e9..09acf1bb7b 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/CompressionHttpHandlerFactory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/CompressionHttpHandlerFactory.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.undertow; +package org.springframework.boot.web.server.undertow; import java.util.ArrayList; import java.util.List; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/ConfigurableUndertowWebServerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/ConfigurableUndertowWebServerFactory.java similarity index 93% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/ConfigurableUndertowWebServerFactory.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/ConfigurableUndertowWebServerFactory.java index 8cdf9766cd..9c51a8b057 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/ConfigurableUndertowWebServerFactory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/ConfigurableUndertowWebServerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.undertow; +package org.springframework.boot.web.server.undertow; import java.io.File; import java.util.Collection; @@ -27,9 +27,7 @@ import org.springframework.boot.web.server.ConfigurableWebServerFactory; * {@link ConfigurableWebServerFactory} for Undertow-specific features. * * @author Brian Clozel - * @since 2.0.0 - * @see UndertowServletWebServerFactory - * @see UndertowReactiveWebServerFactory + * @since 4.0.0 */ public interface ConfigurableUndertowWebServerFactory extends ConfigurableWebServerFactory { @@ -37,7 +35,7 @@ public interface ConfigurableUndertowWebServerFactory extends ConfigurableWebSer * Set {@link UndertowBuilderCustomizer}s that should be applied to the Undertow * {@link Builder}. Calling this method will replace any existing customizers. * @param customizers the customizers to set - * @since 2.3.0 + * @since 4.0.0 */ void setBuilderCustomizers(Collection customizers); diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/HttpHandlerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/HttpHandlerFactory.java similarity index 86% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/HttpHandlerFactory.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/HttpHandlerFactory.java index 581a673485..c537e5e5b5 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/HttpHandlerFactory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/HttpHandlerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,13 +14,15 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.undertow; +package org.springframework.boot.web.server.undertow; import java.io.Closeable; import io.undertow.server.HttpHandler; import io.undertow.server.handlers.GracefulShutdownHandler; +import org.springframework.boot.web.server.servlet.undertow.UndertowServletWebServer; + /** * Factory used by {@link UndertowServletWebServer} to add {@link HttpHandler * HttpHandlers}. Instances returned from this factory may optionally implement the @@ -31,7 +33,7 @@ import io.undertow.server.handlers.GracefulShutdownHandler; * * * @author Phillip Webb - * @since 2.3.0 + * @since 4.0.0 */ @FunctionalInterface public interface HttpHandlerFactory { diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/SslBuilderCustomizer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/SslBuilderCustomizer.java similarity index 98% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/SslBuilderCustomizer.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/SslBuilderCustomizer.java index d6556dbf0a..29f776233a 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/SslBuilderCustomizer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/SslBuilderCustomizer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.undertow; +package org.springframework.boot.web.server.undertow; import java.net.InetAddress; import java.util.Map; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowBuilderCustomizer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/UndertowBuilderCustomizer.java similarity index 81% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowBuilderCustomizer.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/UndertowBuilderCustomizer.java index 29561e787d..4830171aa5 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowBuilderCustomizer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/UndertowBuilderCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,15 +14,17 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.undertow; +package org.springframework.boot.web.server.undertow; import io.undertow.Undertow.Builder; +import org.springframework.boot.web.server.servlet.undertow.UndertowServletWebServerFactory; + /** * Callback interface that can be used to customize an Undertow {@link Builder}. * * @author Andy Wilkinson - * @since 2.0.0 + * @since 4.0.0 * @see UndertowServletWebServerFactory */ @FunctionalInterface diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowWebServer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/UndertowWebServer.java similarity index 97% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowWebServer.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/UndertowWebServer.java index eb54a5883d..06b5797a89 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowWebServer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/UndertowWebServer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.undertow; +package org.springframework.boot.web.server.undertow; import java.io.Closeable; import java.io.IOException; @@ -47,7 +47,7 @@ import org.springframework.util.StringUtils; /** * {@link WebServer} that can be used to control an Undertow web server. Usually this - * class should be created using the {@link UndertowReactiveWebServerFactory} and not + * class should be created using a {@link ConfigurableUndertowWebServerFactory} and not * directly. * * @author Ivan Sopov @@ -55,7 +55,7 @@ import org.springframework.util.StringUtils; * @author Eddú Meléndez * @author Christoph Dreis * @author Brian Clozel - * @since 2.0.0 + * @since 4.0.0 */ public class UndertowWebServer implements WebServer { @@ -93,7 +93,7 @@ public class UndertowWebServer implements WebServer { * @param builder the builder * @param httpHandlerFactories the handler factories * @param autoStart if the server should be started - * @since 2.3.0 + * @since 4.0.0 */ public UndertowWebServer(Undertow.Builder builder, Iterable httpHandlerFactories, boolean autoStart) { @@ -117,7 +117,7 @@ public class UndertowWebServer implements WebServer { } this.undertow.start(); this.started = true; - String message = getStartLogMessage(); + String message = getStartedLogMessage(); logger.info(message); } catch (Exception ex) { @@ -302,7 +302,7 @@ public class UndertowWebServer implements WebServer { * Returns the {@link Undertow Undertow server}. Returns {@code null} until the server * has been started. * @return the Undertow server or {@code null} if the server hasn't been started yet - * @since 3.3.0 + * @since 4.0.0 */ public Undertow getUndertow() { return this.undertow; @@ -342,7 +342,7 @@ public class UndertowWebServer implements WebServer { } } - protected String getStartLogMessage() { + protected String getStartedLogMessage() { return "Undertow started on " + getPortsDescription(); } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowWebServerFactoryDelegate.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/UndertowWebServerFactory.java similarity index 75% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowWebServerFactoryDelegate.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/UndertowWebServerFactory.java index ebae149797..4ab7a2fed2 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowWebServerFactoryDelegate.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/UndertowWebServerFactory.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.undertow; +package org.springframework.boot.web.server.undertow; import java.io.File; import java.net.InetAddress; @@ -42,14 +42,13 @@ import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** - * Delegate class used by {@link UndertowServletWebServerFactory} and - * {@link UndertowReactiveWebServerFactory}. + * Base class for factories that produce an {@link UndertowWebServer}. * - * @author Phillip Webb * @author Andy Wilkinson - * @author Scott Frederick + * @since 4.0.0 */ -class UndertowWebServerFactoryDelegate { +public abstract class UndertowWebServerFactory extends AbstractConfigurableWebServerFactory + implements ConfigurableUndertowWebServerFactory { private Set builderCustomizers = new LinkedHashSet<>(); @@ -75,77 +74,97 @@ class UndertowWebServerFactoryDelegate { private boolean useForwardHeaders; - void setBuilderCustomizers(Collection customizers) { + protected UndertowWebServerFactory() { + } + + protected UndertowWebServerFactory(int port) { + super(port); + } + + public Collection getBuilderCustomizers() { + return this.builderCustomizers; + } + + @Override + public void setBuilderCustomizers(Collection customizers) { Assert.notNull(customizers, "'customizers' must not be null"); this.builderCustomizers = new LinkedHashSet<>(customizers); } - void addBuilderCustomizers(UndertowBuilderCustomizer... customizers) { + @Override + public void addBuilderCustomizers(UndertowBuilderCustomizer... customizers) { Assert.notNull(customizers, "'customizers' must not be null"); this.builderCustomizers.addAll(Arrays.asList(customizers)); } - Collection getBuilderCustomizers() { - return this.builderCustomizers; - } - - void setBufferSize(Integer bufferSize) { + @Override + public void setBufferSize(Integer bufferSize) { this.bufferSize = bufferSize; } - void setIoThreads(Integer ioThreads) { + @Override + public void setIoThreads(Integer ioThreads) { this.ioThreads = ioThreads; } - void setWorkerThreads(Integer workerThreads) { + @Override + public void setWorkerThreads(Integer workerThreads) { this.workerThreads = workerThreads; } - void setUseDirectBuffers(Boolean directBuffers) { + @Override + public void setUseDirectBuffers(Boolean directBuffers) { this.directBuffers = directBuffers; } - void setAccessLogDirectory(File accessLogDirectory) { + @Override + public void setAccessLogDirectory(File accessLogDirectory) { this.accessLogDirectory = accessLogDirectory; } - void setAccessLogPattern(String accessLogPattern) { + @Override + public void setAccessLogPattern(String accessLogPattern) { this.accessLogPattern = accessLogPattern; } - void setAccessLogPrefix(String accessLogPrefix) { + @Override + public void setAccessLogPrefix(String accessLogPrefix) { this.accessLogPrefix = accessLogPrefix; } - String getAccessLogPrefix() { + public String getAccessLogPrefix() { return this.accessLogPrefix; } - void setAccessLogSuffix(String accessLogSuffix) { + @Override + public void setAccessLogSuffix(String accessLogSuffix) { this.accessLogSuffix = accessLogSuffix; } - void setAccessLogEnabled(boolean accessLogEnabled) { + @Override + public void setAccessLogEnabled(boolean accessLogEnabled) { this.accessLogEnabled = accessLogEnabled; } - boolean isAccessLogEnabled() { + public boolean isAccessLogEnabled() { return this.accessLogEnabled; } - void setAccessLogRotate(boolean accessLogRotate) { + @Override + public void setAccessLogRotate(boolean accessLogRotate) { this.accessLogRotate = accessLogRotate; } - void setUseForwardHeaders(boolean useForwardHeaders) { + @Override + public void setUseForwardHeaders(boolean useForwardHeaders) { this.useForwardHeaders = useForwardHeaders; } - boolean isUseForwardHeaders() { + public boolean isUseForwardHeaders() { return this.useForwardHeaders; } - Builder createBuilder(AbstractConfigurableWebServerFactory factory, Supplier sslBundleSupplier, + public Builder createBuilder(AbstractConfigurableWebServerFactory factory, Supplier sslBundleSupplier, Supplier> serverNameSslBundlesSupplier) { InetAddress address = factory.getAddress(); int port = factory.getPort(); @@ -182,7 +201,7 @@ class UndertowWebServerFactoryDelegate { return builder; } - List createHttpHandlerFactories(AbstractConfigurableWebServerFactory webServerFactory, + public List createHttpHandlerFactories(AbstractConfigurableWebServerFactory webServerFactory, HttpHandlerFactory... initialHttpHandlerFactories) { List factories = createHttpHandlerFactories(webServerFactory.getCompression(), this.useForwardHeaders, webServerFactory.getServerHeader(), webServerFactory.getShutdown(), diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/package-info.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/package-info.java similarity index 61% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/package-info.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/package-info.java index eed58b0a8a..98d71eff82 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/package-info.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/undertow/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,8 +15,9 @@ */ /** - * Embedded reactive web server implementation backed by Netty. + * Reactive and servlet web server implementations backed by Undertow. * - * @see org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory + * @see org.springframework.boot.web.server.servlet.undertow.UndertowServletWebServerFactory + * @see org.springframework.boot.web.server.reactive.undertow.UndertowReactiveWebServerFactory */ -package org.springframework.boot.web.embedded.netty; +package org.springframework.boot.web.server.undertow; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/AbstractFilterRegistrationBean.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/AbstractFilterRegistrationBean.java index 2ca818bdfb..c81147937c 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/AbstractFilterRegistrationBean.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/AbstractFilterRegistrationBean.java @@ -29,6 +29,7 @@ import jakarta.servlet.FilterRegistration; import jakarta.servlet.FilterRegistration.Dynamic; import jakarta.servlet.ServletContext; +import org.springframework.boot.web.server.servlet.ServletContextInitializer; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.CollectionUtils; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/DelegatingFilterProxyRegistrationBean.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/DelegatingFilterProxyRegistrationBean.java index 6772c58c28..061a50c58a 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/DelegatingFilterProxyRegistrationBean.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/DelegatingFilterProxyRegistrationBean.java @@ -21,6 +21,7 @@ import jakarta.servlet.ServletContext; import jakarta.servlet.ServletException; import org.springframework.beans.BeansException; +import org.springframework.boot.web.server.servlet.ServletContextInitializer; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.util.Assert; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/FilterRegistrationBean.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/FilterRegistrationBean.java index 977a7312fe..f87630f349 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/FilterRegistrationBean.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/FilterRegistrationBean.java @@ -19,6 +19,7 @@ package org.springframework.boot.web.servlet; import jakarta.servlet.Filter; import jakarta.servlet.ServletContext; +import org.springframework.boot.web.server.servlet.ServletContextInitializer; import org.springframework.util.Assert; /** diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/RegistrationBean.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/RegistrationBean.java index 2e3e675c6a..4a72d87728 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/RegistrationBean.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/RegistrationBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ import jakarta.servlet.ServletException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.boot.web.server.servlet.ServletContextInitializer; import org.springframework.core.Ordered; import org.springframework.util.StringUtils; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java index 195a707cd0..2a02ecb896 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java @@ -42,6 +42,7 @@ import org.apache.commons.logging.LogFactory; import org.springframework.aop.scope.ScopedProxyUtils; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.boot.web.server.servlet.ServletContextInitializer; import org.springframework.core.Ordered; import org.springframework.core.annotation.AnnotationAwareOrderComparator; import org.springframework.core.annotation.Order; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletListenerRegistrationBean.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletListenerRegistrationBean.java index c7bed435cb..f82004b629 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletListenerRegistrationBean.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletListenerRegistrationBean.java @@ -30,6 +30,7 @@ import jakarta.servlet.http.HttpSessionAttributeListener; import jakarta.servlet.http.HttpSessionIdListener; import jakarta.servlet.http.HttpSessionListener; +import org.springframework.boot.web.server.servlet.ServletContextInitializer; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletRegistrationBean.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletRegistrationBean.java index 616d60ddfd..1b12c3c134 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletRegistrationBean.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletRegistrationBean.java @@ -26,6 +26,7 @@ import jakarta.servlet.Servlet; import jakarta.servlet.ServletContext; import jakarta.servlet.ServletRegistration; +import org.springframework.boot.web.server.servlet.ServletContextInitializer; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/WebListenerHandler.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/WebListenerHandler.java index b001500293..868a431a76 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/WebListenerHandler.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/WebListenerHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ import jakarta.servlet.annotation.WebListener; import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.boot.web.server.servlet.WebListenerRegistry; /** * Handler for {@link WebListener @WebListener}-annotated classes. diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/WebListenerRegistrar.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/WebListenerRegistrar.java index deb8333fee..d6e8ed44ca 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/WebListenerRegistrar.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/WebListenerRegistrar.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,8 @@ package org.springframework.boot.web.servlet; import jakarta.servlet.annotation.WebListener; +import org.springframework.boot.web.server.servlet.WebListenerRegistry; + /** * Interface to be implemented by types that register {@link WebListener @WebListeners}. * diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/context/ServletWebServerApplicationContext.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/context/ServletWebServerApplicationContext.java index 45e3958d1d..b5254a1061 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/context/ServletWebServerApplicationContext.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/context/ServletWebServerApplicationContext.java @@ -43,11 +43,11 @@ import org.springframework.boot.web.context.ConfigurableWebServerApplicationCont import org.springframework.boot.web.context.MissingWebServerFactoryBeanException; import org.springframework.boot.web.context.WebServerGracefulShutdownLifecycle; import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.servlet.ServletContextInitializer; +import org.springframework.boot.web.server.servlet.ServletWebServerFactory; import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.boot.web.servlet.ServletContextInitializerBeans; import org.springframework.boot.web.servlet.ServletRegistrationBean; -import org.springframework.boot.web.servlet.server.ServletWebServerFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextException; import org.springframework.core.io.Resource; @@ -234,7 +234,7 @@ public class ServletWebServerApplicationContext extends GenericWebApplicationCon * @return the self initializer * @see #prepareWebApplicationContext(ServletContext) */ - private org.springframework.boot.web.servlet.ServletContextInitializer getSelfInitializer() { + private org.springframework.boot.web.server.servlet.ServletContextInitializer getSelfInitializer() { return this::selfInitialize; } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactory.java deleted file mode 100644 index 97b29bcb8e..0000000000 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactory.java +++ /dev/null @@ -1,371 +0,0 @@ -/* - * Copyright 2012-2025 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.web.servlet.server; - -import java.io.File; -import java.net.URL; -import java.nio.charset.Charset; -import java.time.Duration; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; - -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; -import jakarta.servlet.SessionCookieConfig; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.boot.context.properties.PropertyMapper; -import org.springframework.boot.web.server.AbstractConfigurableWebServerFactory; -import org.springframework.boot.web.server.Cookie; -import org.springframework.boot.web.server.MimeMappings; -import org.springframework.boot.web.servlet.ServletContextInitializer; -import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; - -/** - * Abstract base class for {@link ConfigurableServletWebServerFactory} implementations. - * - * @author Phillip Webb - * @author Dave Syer - * @author Andy Wilkinson - * @author Stephane Nicoll - * @author Ivan Sopov - * @author Eddú Meléndez - * @author Brian Clozel - * @since 2.0.0 - */ -public abstract class AbstractServletWebServerFactory extends AbstractConfigurableWebServerFactory - implements ConfigurableServletWebServerFactory { - - protected final Log logger = LogFactory.getLog(getClass()); - - private String contextPath = ""; - - private String displayName; - - private Session session = new Session(); - - private boolean registerDefaultServlet; - - private MimeMappings mimeMappings = MimeMappings.lazyCopy(MimeMappings.DEFAULT); - - private List initializers = new ArrayList<>(); - - private Jsp jsp = new Jsp(); - - private Map localeCharsetMappings = new HashMap<>(); - - private Map initParameters = Collections.emptyMap(); - - private List cookieSameSiteSuppliers = new ArrayList<>(); - - private final DocumentRoot documentRoot = new DocumentRoot(this.logger); - - private final StaticResourceJars staticResourceJars = new StaticResourceJars(); - - private final Set webListenerClassNames = new HashSet<>(); - - /** - * Create a new {@link AbstractServletWebServerFactory} instance. - */ - public AbstractServletWebServerFactory() { - } - - /** - * Create a new {@link AbstractServletWebServerFactory} instance with the specified - * port. - * @param port the port number for the web server - */ - public AbstractServletWebServerFactory(int port) { - super(port); - } - - /** - * Create a new {@link AbstractServletWebServerFactory} instance with the specified - * context path and port. - * @param contextPath the context path for the web server - * @param port the port number for the web server - */ - public AbstractServletWebServerFactory(String contextPath, int port) { - super(port); - checkContextPath(contextPath); - this.contextPath = contextPath; - } - - /** - * Returns the context path for the web server. The path will start with "/" and not - * end with "/". The root context is represented by an empty string. - * @return the context path - */ - public String getContextPath() { - return this.contextPath; - } - - @Override - public void setContextPath(String contextPath) { - checkContextPath(contextPath); - this.contextPath = contextPath; - } - - private void checkContextPath(String contextPath) { - Assert.notNull(contextPath, "'contextPath' must not be null"); - if (!contextPath.isEmpty()) { - if ("/".equals(contextPath)) { - throw new IllegalArgumentException("Root ContextPath must be specified using an empty string"); - } - if (!contextPath.startsWith("/") || contextPath.endsWith("/")) { - throw new IllegalArgumentException("ContextPath must start with '/' and not end with '/'"); - } - } - } - - public String getDisplayName() { - return this.displayName; - } - - @Override - public void setDisplayName(String displayName) { - this.displayName = displayName; - } - - /** - * Flag to indicate that the default servlet should be registered. - * @return true if the default servlet is to be registered - */ - public boolean isRegisterDefaultServlet() { - return this.registerDefaultServlet; - } - - @Override - public void setRegisterDefaultServlet(boolean registerDefaultServlet) { - this.registerDefaultServlet = registerDefaultServlet; - } - - /** - * Returns the mime-type mappings. - * @return the mimeMappings the mime-type mappings. - */ - public MimeMappings getMimeMappings() { - return this.mimeMappings; - } - - @Override - public void setMimeMappings(MimeMappings mimeMappings) { - Assert.notNull(mimeMappings, "'mimeMappings' must not be null"); - this.mimeMappings = new MimeMappings(mimeMappings); - } - - @Override - public void addMimeMappings(MimeMappings mimeMappings) { - mimeMappings.forEach((mapping) -> this.mimeMappings.add(mapping.getExtension(), mapping.getMimeType())); - } - - /** - * Returns the document root which will be used by the web context to serve static - * files. - * @return the document root - */ - public File getDocumentRoot() { - return this.documentRoot.getDirectory(); - } - - @Override - public void setDocumentRoot(File documentRoot) { - this.documentRoot.setDirectory(documentRoot); - } - - @Override - public void setInitializers(List initializers) { - Assert.notNull(initializers, "'initializers' must not be null"); - this.initializers = new ArrayList<>(initializers); - } - - @Override - public void addInitializers(ServletContextInitializer... initializers) { - Assert.notNull(initializers, "'initializers' must not be null"); - this.initializers.addAll(Arrays.asList(initializers)); - } - - public Jsp getJsp() { - return this.jsp; - } - - @Override - public void setJsp(Jsp jsp) { - this.jsp = jsp; - } - - public Session getSession() { - return this.session; - } - - @Override - public void setSession(Session session) { - this.session = session; - } - - /** - * Return the Locale to Charset mappings. - * @return the charset mappings - */ - public Map getLocaleCharsetMappings() { - return this.localeCharsetMappings; - } - - @Override - public void setLocaleCharsetMappings(Map localeCharsetMappings) { - Assert.notNull(localeCharsetMappings, "'localeCharsetMappings' must not be null"); - this.localeCharsetMappings = localeCharsetMappings; - } - - @Override - public void setInitParameters(Map initParameters) { - this.initParameters = initParameters; - } - - public Map getInitParameters() { - return this.initParameters; - } - - @Override - public void setCookieSameSiteSuppliers(List cookieSameSiteSuppliers) { - Assert.notNull(cookieSameSiteSuppliers, "'cookieSameSiteSuppliers' must not be null"); - this.cookieSameSiteSuppliers = new ArrayList<>(cookieSameSiteSuppliers); - } - - @Override - public void addCookieSameSiteSuppliers(CookieSameSiteSupplier... cookieSameSiteSuppliers) { - Assert.notNull(cookieSameSiteSuppliers, "'cookieSameSiteSuppliers' must not be null"); - this.cookieSameSiteSuppliers.addAll(Arrays.asList(cookieSameSiteSuppliers)); - } - - public List getCookieSameSiteSuppliers() { - return this.cookieSameSiteSuppliers; - } - - /** - * Utility method that can be used by subclasses wishing to combine the specified - * {@link ServletContextInitializer} parameters with those defined in this instance. - * @param initializers the initializers to merge - * @return a complete set of merged initializers (with the specified parameters - * appearing first) - */ - protected final ServletContextInitializer[] mergeInitializers(ServletContextInitializer... initializers) { - List mergedInitializers = new ArrayList<>(); - mergedInitializers.add((servletContext) -> this.initParameters.forEach(servletContext::setInitParameter)); - mergedInitializers.add(new SessionConfiguringInitializer(this.session)); - mergedInitializers.addAll(Arrays.asList(initializers)); - mergedInitializers.addAll(this.initializers); - return mergedInitializers.toArray(new ServletContextInitializer[0]); - } - - /** - * Returns whether the JSP servlet should be registered with the web server. - * @return {@code true} if the servlet should be registered, otherwise {@code false} - */ - protected boolean shouldRegisterJspServlet() { - return this.jsp != null && this.jsp.getRegistered() - && ClassUtils.isPresent(this.jsp.getClassName(), getClass().getClassLoader()); - } - - /** - * Returns the absolute document root when it points to a valid directory, logging a - * warning and returning {@code null} otherwise. - * @return the valid document root - */ - protected final File getValidDocumentRoot() { - return this.documentRoot.getValidDirectory(); - } - - protected final List getUrlsOfJarsWithMetaInfResources() { - return this.staticResourceJars.getUrls(); - } - - protected final File getValidSessionStoreDir() { - return getValidSessionStoreDir(true); - } - - protected final File getValidSessionStoreDir(boolean mkdirs) { - return this.session.getSessionStoreDirectory().getValidDirectory(mkdirs); - } - - @Override - public void addWebListeners(String... webListenerClassNames) { - this.webListenerClassNames.addAll(Arrays.asList(webListenerClassNames)); - } - - protected final Set getWebListenerClassNames() { - return this.webListenerClassNames; - } - - /** - * {@link ServletContextInitializer} to apply appropriate parts of the {@link Session} - * configuration. - */ - private static class SessionConfiguringInitializer implements ServletContextInitializer { - - private final Session session; - - SessionConfiguringInitializer(Session session) { - this.session = session; - } - - @Override - public void onStartup(ServletContext servletContext) throws ServletException { - if (this.session.getTrackingModes() != null) { - servletContext.setSessionTrackingModes(unwrap(this.session.getTrackingModes())); - } - configureSessionCookie(servletContext.getSessionCookieConfig()); - } - - private void configureSessionCookie(SessionCookieConfig config) { - Cookie cookie = this.session.getCookie(); - PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); - map.from(cookie::getName).to(config::setName); - map.from(cookie::getDomain).to(config::setDomain); - map.from(cookie::getPath).to(config::setPath); - map.from(cookie::getHttpOnly).to(config::setHttpOnly); - map.from(cookie::getSecure).to(config::setSecure); - map.from(cookie::getMaxAge).asInt(Duration::getSeconds).to(config::setMaxAge); - map.from(cookie::getPartitioned) - .as(Object::toString) - .to((partitioned) -> config.setAttribute("Partitioned", partitioned)); - } - - private Set unwrap(Set modes) { - if (modes == null) { - return null; - } - Set result = new LinkedHashSet<>(); - for (Session.SessionTrackingMode mode : modes) { - result.add(jakarta.servlet.SessionTrackingMode.valueOf(mode.name())); - } - return result; - } - - } - -} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/support/SpringBootServletInitializer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/support/SpringBootServletInitializer.java index e21e486cab..c8a8b84227 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/support/SpringBootServletInitializer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/support/SpringBootServletInitializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,7 +35,7 @@ import org.springframework.boot.builder.ParentContextApplicationContextInitializ import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; import org.springframework.boot.context.logging.LoggingApplicationListener; -import org.springframework.boot.web.servlet.ServletContextInitializer; +import org.springframework.boot.web.server.servlet.ServletContextInitializer; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationListener; diff --git a/spring-boot-project/spring-boot/src/main/resources/META-INF/spring.factories b/spring-boot-project/spring-boot/src/main/resources/META-INF/spring.factories index 0852534a5c..b47204f480 100644 --- a/spring-boot-project/spring-boot/src/main/resources/META-INF/spring.factories +++ b/spring-boot-project/spring-boot/src/main/resources/META-INF/spring.factories @@ -82,7 +82,7 @@ org.springframework.boot.diagnostics.analyzer.UnboundConfigurationPropertyFailur org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer,\ org.springframework.boot.liquibase.LiquibaseChangelogMissingFailureAnalyzer,\ org.springframework.boot.web.context.MissingWebServerFactoryBeanFailureAnalyzer,\ -org.springframework.boot.web.embedded.tomcat.ConnectorStartFailureAnalyzer,\ +org.springframework.boot.web.server.tomcat.ConnectorStartFailureAnalyzer org.springframework.boot.web.server.PortInUseFailureAnalyzer # Failure Analysis Reporters diff --git a/spring-boot-project/spring-boot/src/main/resources/META-INF/spring/aot.factories b/spring-boot-project/spring-boot/src/main/resources/META-INF/spring/aot.factories index 5d4127122e..7f012debcb 100644 --- a/spring-boot-project/spring-boot/src/main/resources/META-INF/spring/aot.factories +++ b/spring-boot-project/spring-boot/src/main/resources/META-INF/spring/aot.factories @@ -12,9 +12,9 @@ org.springframework.boot.logging.java.JavaLoggingSystemRuntimeHints,\ org.springframework.boot.logging.logback.LogbackRuntimeHints,\ org.springframework.boot.logging.structured.ElasticCommonSchemaProperties$ElasticCommonSchemaPropertiesRuntimeHints,\ org.springframework.boot.logging.structured.GraylogExtendedLogFormatProperties$GraylogExtendedLogFormatPropertiesRuntimeHints,\ -org.springframework.boot.logging.structured.StructuredLoggingJsonProperties$StructuredLoggingJsonPropertiesRuntimeHints,\ -org.springframework.boot.web.embedded.undertow.UndertowWebServer$UndertowWebServerRuntimeHints,\ -org.springframework.boot.web.server.MimeMappings$MimeMappingsRuntimeHints +org.springframework.boot.logging.structured.StructuredLoggingJsonProperties$StructuredLoggingJsonPropertiesRuntimeHints +org.springframework.boot.web.server.MimeMappings$MimeMappingsRuntimeHints,\ +org.springframework.boot.web.server.undertow.UndertowWebServer$UndertowWebServerRuntimeHints org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor=\ org.springframework.boot.context.properties.ConfigurationPropertiesBeanFactoryInitializationAotProcessor,\ diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java index 97187aad80..8dffb37b05 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java @@ -76,11 +76,11 @@ import org.springframework.boot.testsupport.classpath.ForkedClassPath; import org.springframework.boot.testsupport.classpath.resources.WithResource; import org.springframework.boot.testsupport.system.CapturedOutput; import org.springframework.boot.testsupport.system.OutputCaptureExtension; -import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext; import org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext; import org.springframework.boot.web.reactive.context.StandardReactiveWebEnvironment; +import org.springframework.boot.web.server.reactive.netty.NettyReactiveWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/http/client/AbstractClientHttpRequestFactoryBuilderTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/http/client/AbstractClientHttpRequestFactoryBuilderTests.java index c405b19d7d..314cb32465 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/http/client/AbstractClientHttpRequestFactoryBuilderTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/http/client/AbstractClientHttpRequestFactoryBuilderTests.java @@ -41,10 +41,10 @@ import org.springframework.boot.ssl.jks.JksSslStoreBundle; import org.springframework.boot.ssl.jks.JksSslStoreDetails; import org.springframework.boot.testsupport.classpath.resources.WithPackageResources; import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.Ssl; import org.springframework.boot.web.server.Ssl.ClientAuth; import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.client.ClientHttpRequest; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/http/client/reactive/AbstractClientHttpConnectorBuilderTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/http/client/reactive/AbstractClientHttpConnectorBuilderTests.java index 7afc1f9c4a..2fbed94d29 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/http/client/reactive/AbstractClientHttpConnectorBuilderTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/http/client/reactive/AbstractClientHttpConnectorBuilderTests.java @@ -41,10 +41,10 @@ import org.springframework.boot.ssl.jks.JksSslStoreBundle; import org.springframework.boot.ssl.jks.JksSslStoreDetails; import org.springframework.boot.testsupport.classpath.resources.WithPackageResources; import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.Ssl; import org.springframework.boot.web.server.Ssl.ClientAuth; import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.client.reactive.ClientHttpConnector; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/AbstractClientHttpRequestFactoriesTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/AbstractClientHttpRequestFactoriesTests.java index af7e9c66f6..41d0571e66 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/AbstractClientHttpRequestFactoriesTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/AbstractClientHttpRequestFactoriesTests.java @@ -38,10 +38,10 @@ import org.springframework.boot.ssl.jks.JksSslStoreBundle; import org.springframework.boot.ssl.jks.JksSslStoreDetails; import org.springframework.boot.testsupport.classpath.resources.WithPackageResources; import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.Ssl; import org.springframework.boot.web.server.Ssl.ClientAuth; import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.http.HttpMethod; import org.springframework.http.client.ClientHttpRequest; import org.springframework.http.client.ClientHttpRequestFactory; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/context/MissingWebServerFactoryBeanFailureAnalyzerTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/context/MissingWebServerFactoryBeanFailureAnalyzerTests.java index fb30be29ca..d9ad1217c0 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/context/MissingWebServerFactoryBeanFailureAnalyzerTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/context/MissingWebServerFactoryBeanFailureAnalyzerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,9 +20,9 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.diagnostics.FailureAnalysis; import org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext; -import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.ReactiveWebServerFactory; +import org.springframework.boot.web.server.servlet.ServletWebServerFactory; import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext; -import org.springframework.boot.web.servlet.server.ServletWebServerFactory; import org.springframework.context.ApplicationContextException; import org.springframework.context.ConfigurableApplicationContext; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/context/AnnotationConfigReactiveWebServerApplicationContextTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/context/AnnotationConfigReactiveWebServerApplicationContextTests.java index 73c96e8833..998d40cb63 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/context/AnnotationConfigReactiveWebServerApplicationContextTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/context/AnnotationConfigReactiveWebServerApplicationContextTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,8 +20,8 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.web.reactive.context.WebServerManager.DelayedInitializationHttpHandler; import org.springframework.boot.web.reactive.context.config.ExampleReactiveWebServerApplicationConfiguration; -import org.springframework.boot.web.reactive.server.MockReactiveWebServerFactory; -import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.MockReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.ReactiveWebServerFactory; import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/context/ReactiveWebServerApplicationContextTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/context/ReactiveWebServerApplicationContextTests.java index 01809b3bfb..98ccb0d6a0 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/context/ReactiveWebServerApplicationContextTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/context/ReactiveWebServerApplicationContextTests.java @@ -29,8 +29,8 @@ import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.boot.availability.AvailabilityChangeEvent; import org.springframework.boot.availability.ReadinessState; import org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer; -import org.springframework.boot.web.reactive.server.MockReactiveWebServerFactory; import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.reactive.MockReactiveWebServerFactory; import org.springframework.context.ApplicationContextException; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/context/config/ExampleReactiveWebServerApplicationConfiguration.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/context/config/ExampleReactiveWebServerApplicationConfiguration.java index 95a56637f3..66235adb10 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/context/config/ExampleReactiveWebServerApplicationConfiguration.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/context/config/ExampleReactiveWebServerApplicationConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,7 @@ package org.springframework.boot.web.reactive.context.config; -import org.springframework.boot.web.reactive.server.MockReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.MockReactiveWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.server.reactive.HttpHandler; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/package-info.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/jetty/JettyAccess.java similarity index 58% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/package-info.java rename to spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/jetty/JettyAccess.java index 5fab4da38d..75bb16c3a1 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/package-info.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/jetty/JettyAccess.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,10 +14,21 @@ * limitations under the License. */ +package org.springframework.boot.web.server.jetty; + /** - * Embedded reactive and servlet web server implementations backed by Tomcat. + * Helper class to provide public access to package-private methods for testing purposes. * - * @see org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory - * @see org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory + * @author Andy Wilkinson */ -package org.springframework.boot.web.embedded.tomcat; +public final class JettyAccess { + + private JettyAccess() { + + } + + public static String getStartedLogMessage(JettyWebServer jettyWebServer) { + return jettyWebServer.getStartedLogMessage(); + } + +} diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/SslServerCustomizerTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/jetty/SslServerCustomizerTests.java similarity index 99% rename from spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/SslServerCustomizerTests.java rename to spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/jetty/SslServerCustomizerTests.java index 43f2dfb856..3a18a4c9ea 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/SslServerCustomizerTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/jetty/SslServerCustomizerTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.jetty; +package org.springframework.boot.web.server.jetty; import java.net.InetSocketAddress; import java.util.ArrayList; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/server/AbstractReactiveWebServerFactoryTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/reactive/AbstractReactiveWebServerFactoryTests.java similarity index 95% rename from spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/server/AbstractReactiveWebServerFactoryTests.java rename to spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/reactive/AbstractReactiveWebServerFactoryTests.java index 66ae7af74a..6c264d33d8 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/server/AbstractReactiveWebServerFactoryTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/reactive/AbstractReactiveWebServerFactoryTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.reactive.server; +package org.springframework.boot.web.server.reactive; import java.io.InputStream; import java.net.InetSocketAddress; @@ -111,11 +111,11 @@ public abstract class AbstractReactiveWebServerFactoryTests { } } - protected abstract AbstractReactiveWebServerFactory getFactory(); + protected abstract ConfigurableReactiveWebServerFactory getFactory(); @Test void specificPort() throws Exception { - AbstractReactiveWebServerFactory factory = getFactory(); + ConfigurableReactiveWebServerFactory factory = getFactory(); int specificPort = doWithRetry(() -> { factory.setPort(0); this.webServer = factory.getWebServer(new EchoHandler()); @@ -135,7 +135,7 @@ public abstract class AbstractReactiveWebServerFactoryTests { @Test protected void restartAfterStop() throws Exception { - AbstractReactiveWebServerFactory factory = getFactory(); + ConfigurableReactiveWebServerFactory factory = getFactory(); this.webServer = factory.getWebServer(new EchoHandler()); this.webServer.start(); int port = this.webServer.getPort(); @@ -159,7 +159,7 @@ public abstract class AbstractReactiveWebServerFactoryTests { @Test void portIsMinusOneWhenConnectionIsClosed() { - AbstractReactiveWebServerFactory factory = getFactory(); + ConfigurableReactiveWebServerFactory factory = getFactory(); this.webServer = factory.getWebServer(new EchoHandler()); this.webServer.start(); assertThat(this.webServer.getPort()).isGreaterThan(0); @@ -181,7 +181,7 @@ public abstract class AbstractReactiveWebServerFactoryTests { } protected final void testBasicSslWithKeyStore(String keyStore, String keyPassword) { - AbstractReactiveWebServerFactory factory = getFactory(); + ConfigurableReactiveWebServerFactory factory = getFactory(); Ssl ssl = new Ssl(); ssl.setKeyStore(keyStore); ssl.setKeyPassword(keyPassword); @@ -208,7 +208,7 @@ public abstract class AbstractReactiveWebServerFactoryTests { void sslWithValidAlias() { String keyStore = "classpath:test.jks"; String keyPassword = "password"; - AbstractReactiveWebServerFactory factory = getFactory(); + ConfigurableReactiveWebServerFactory factory = getFactory(); Ssl ssl = new Ssl(); ssl.setKeyStore(keyStore); ssl.setKeyStorePassword("secret"); @@ -238,7 +238,7 @@ public abstract class AbstractReactiveWebServerFactoryTests { void sslWithInvalidAliasFailsDuringStartup() { String keyStore = "classpath:test.jks"; String keyPassword = "password"; - AbstractReactiveWebServerFactory factory = getFactory(); + ConfigurableReactiveWebServerFactory factory = getFactory(); Ssl ssl = new Ssl(); ssl.setKeyStore(keyStore); ssl.setKeyPassword(keyPassword); @@ -303,7 +303,7 @@ public abstract class AbstractReactiveWebServerFactoryTests { } protected void testClientAuthSuccess(Ssl sslConfiguration, ReactorClientHttpConnector clientConnector) { - AbstractReactiveWebServerFactory factory = getFactory(); + ConfigurableReactiveWebServerFactory factory = getFactory(); factory.setSsl(sslConfiguration); this.webServer = factory.getWebServer(new EchoHandler()); this.webServer.start(); @@ -356,7 +356,7 @@ public abstract class AbstractReactiveWebServerFactoryTests { } protected void testClientAuthFailure(Ssl sslConfiguration, ReactorClientHttpConnector clientConnector) { - AbstractReactiveWebServerFactory factory = getFactory(); + ConfigurableReactiveWebServerFactory factory = getFactory(); factory.setSsl(sslConfiguration); this.webServer = factory.getWebServer(new EchoHandler()); this.webServer.start(); @@ -449,7 +449,7 @@ public abstract class AbstractReactiveWebServerFactoryTests { @Test void whenThereAreNoInFlightRequestsShutDownGracefullyReturnsTrueBeforePeriodElapses() throws Exception { - AbstractReactiveWebServerFactory factory = getFactory(); + ConfigurableReactiveWebServerFactory factory = getFactory(); factory.setShutdown(Shutdown.GRACEFUL); this.webServer = factory.getWebServer(new EchoHandler()); this.webServer.start(); @@ -461,7 +461,7 @@ public abstract class AbstractReactiveWebServerFactoryTests { @Test void whenARequestRemainsInFlightThenShutDownGracefullyDoesNotInvokeCallbackUntilTheRequestCompletes() throws Exception { - AbstractReactiveWebServerFactory factory = getFactory(); + ConfigurableReactiveWebServerFactory factory = getFactory(); factory.setShutdown(Shutdown.GRACEFUL); BlockingHandler blockingHandler = new BlockingHandler(); this.webServer = factory.getWebServer(blockingHandler); @@ -488,7 +488,7 @@ public abstract class AbstractReactiveWebServerFactoryTests { @Test void givenAnInflightRequestWhenTheServerIsStoppedThenGracefulShutdownCallbackIsCalledWithRequestsActive() throws Exception { - AbstractReactiveWebServerFactory factory = getFactory(); + ConfigurableReactiveWebServerFactory factory = getFactory(); factory.setShutdown(Shutdown.GRACEFUL); BlockingHandler blockingHandler = new BlockingHandler(); this.webServer = factory.getWebServer(blockingHandler); @@ -522,7 +522,7 @@ public abstract class AbstractReactiveWebServerFactoryTests { @Test void whenARequestIsActiveAfterGracefulShutdownEndsThenStopWillComplete() throws InterruptedException { - AbstractReactiveWebServerFactory factory = getFactory(); + ConfigurableReactiveWebServerFactory factory = getFactory(); factory.setShutdown(Shutdown.GRACEFUL); BlockingHandler blockingHandler = new BlockingHandler(); this.webServer = factory.getWebServer(blockingHandler); @@ -549,7 +549,7 @@ public abstract class AbstractReactiveWebServerFactoryTests { @Test void whenARequestIsActiveThenStopWillComplete() throws InterruptedException { - AbstractReactiveWebServerFactory factory = getFactory(); + ConfigurableReactiveWebServerFactory factory = getFactory(); BlockingHandler blockingHandler = new BlockingHandler(); this.webServer = factory.getWebServer(blockingHandler); this.webServer.start(); @@ -575,7 +575,7 @@ public abstract class AbstractReactiveWebServerFactoryTests { @Test protected void whenHttp2IsEnabledAndSslIsDisabledThenH2cCanBeUsed() throws Exception { - AbstractReactiveWebServerFactory factory = getFactory(); + ConfigurableReactiveWebServerFactory factory = getFactory(); Http2 http2 = new Http2(); http2.setEnabled(true); factory.setHttp2(http2); @@ -595,7 +595,7 @@ public abstract class AbstractReactiveWebServerFactoryTests { @Test protected void whenHttp2IsEnabledAndSslIsDisabledThenHttp11CanStillBeUsed() { - AbstractReactiveWebServerFactory factory = getFactory(); + ConfigurableReactiveWebServerFactory factory = getFactory(); Http2 http2 = new Http2(); http2.setEnabled(true); factory.setHttp2(http2); @@ -613,7 +613,7 @@ public abstract class AbstractReactiveWebServerFactoryTests { @Test void startedLogMessageWithSinglePort() { - AbstractReactiveWebServerFactory factory = getFactory(); + ConfigurableReactiveWebServerFactory factory = getFactory(); this.webServer = factory.getWebServer(new EchoHandler()); this.webServer.start(); assertThat(startedLogMessage()).matches( @@ -622,7 +622,7 @@ public abstract class AbstractReactiveWebServerFactoryTests { @Test protected void startedLogMessageWithMultiplePorts() { - AbstractReactiveWebServerFactory factory = getFactory(); + ConfigurableReactiveWebServerFactory factory = getFactory(); addConnector(0, factory); this.webServer = factory.getWebServer(new EchoHandler()); this.webServer.start(); @@ -641,7 +641,7 @@ public abstract class AbstractReactiveWebServerFactoryTests { } protected WebClient prepareCompressionTest(Compression compression, String responseContentType) { - AbstractReactiveWebServerFactory factory = getFactory(); + ConfigurableReactiveWebServerFactory factory = getFactory(); factory.setCompression(compression); this.webServer = factory.getWebServer(new CharsHandler(3000, responseContentType)); this.webServer.start(); @@ -665,7 +665,7 @@ public abstract class AbstractReactiveWebServerFactoryTests { assertThat(response.getHeaders().headerNames()).doesNotContain("X-Test-Compressed"); } - protected void assertForwardHeaderIsUsed(AbstractReactiveWebServerFactory factory) { + protected void assertForwardHeaderIsUsed(ConfigurableReactiveWebServerFactory factory) { this.webServer = factory.getWebServer(new XForwardedHandler()); this.webServer.start(); String body = getWebClient(this.webServer.getPort()).build() @@ -703,7 +703,7 @@ public abstract class AbstractReactiveWebServerFactoryTests { protected abstract String startedLogMessage(); - protected abstract void addConnector(int port, AbstractReactiveWebServerFactory factory); + protected abstract void addConnector(int port, ConfigurableReactiveWebServerFactory factory); public interface BlockedPortAction { diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/JettyReactiveWebServerFactoryTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/reactive/jetty/JettyReactiveWebServerFactoryTests.java similarity index 91% rename from spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/JettyReactiveWebServerFactoryTests.java rename to spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/reactive/jetty/JettyReactiveWebServerFactoryTests.java index adf4549c40..51687fd0a1 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/JettyReactiveWebServerFactoryTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/reactive/jetty/JettyReactiveWebServerFactoryTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.jetty; +package org.springframework.boot.web.server.reactive.jetty; import java.net.ConnectException; import java.net.InetAddress; @@ -31,11 +31,14 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.mockito.InOrder; -import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactory; -import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactoryTests; import org.springframework.boot.web.server.Shutdown; import org.springframework.boot.web.server.Ssl; import org.springframework.boot.web.server.Ssl.ServerNameSslBundle; +import org.springframework.boot.web.server.jetty.JettyAccess; +import org.springframework.boot.web.server.jetty.JettyServerCustomizer; +import org.springframework.boot.web.server.jetty.JettyWebServer; +import org.springframework.boot.web.server.reactive.AbstractReactiveWebServerFactoryTests; +import org.springframework.boot.web.server.reactive.ConfigurableReactiveWebServerFactory; import org.springframework.http.server.reactive.HttpHandler; import org.springframework.web.reactive.function.client.WebClient; @@ -165,11 +168,11 @@ class JettyReactiveWebServerFactoryTests extends AbstractReactiveWebServerFactor @Override protected String startedLogMessage() { - return ((JettyWebServer) this.webServer).getStartedLogMessage(); + return JettyAccess.getStartedLogMessage((JettyWebServer) this.webServer); } @Override - protected void addConnector(int port, AbstractReactiveWebServerFactory factory) { + protected void addConnector(int port, ConfigurableReactiveWebServerFactory factory) { ((JettyReactiveWebServerFactory) factory).addServerCustomizers((server) -> { ServerConnector connector = new ServerConnector(server); connector.setPort(port); diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/netty/NettyReactiveWebServerFactoryTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/reactive/netty/NettyReactiveWebServerFactoryTests.java similarity index 96% rename from spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/netty/NettyReactiveWebServerFactoryTests.java rename to spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/reactive/netty/NettyReactiveWebServerFactoryTests.java index fdd41b0f9a..d21960d70c 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/netty/NettyReactiveWebServerFactoryTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/reactive/netty/NettyReactiveWebServerFactoryTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.netty; +package org.springframework.boot.web.server.reactive.netty; import java.net.ConnectException; import java.net.SocketAddress; @@ -40,11 +40,12 @@ import org.springframework.boot.ssl.SslBundles; import org.springframework.boot.ssl.pem.PemSslStoreBundle; import org.springframework.boot.ssl.pem.PemSslStoreDetails; import org.springframework.boot.testsupport.classpath.resources.WithPackageResources; -import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactory; -import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactoryTests; import org.springframework.boot.web.server.PortInUseException; import org.springframework.boot.web.server.Shutdown; import org.springframework.boot.web.server.Ssl; +import org.springframework.boot.web.server.reactive.AbstractReactiveWebServerFactory; +import org.springframework.boot.web.server.reactive.AbstractReactiveWebServerFactoryTests; +import org.springframework.boot.web.server.reactive.ConfigurableReactiveWebServerFactory; import org.springframework.http.MediaType; import org.springframework.http.client.ReactorResourceFactory; import org.springframework.http.client.reactive.ReactorClientHttpConnector; @@ -228,7 +229,7 @@ class NettyReactiveWebServerFactoryTests extends AbstractReactiveWebServerFactor } @Override - protected void addConnector(int port, AbstractReactiveWebServerFactory factory) { + protected void addConnector(int port, ConfigurableReactiveWebServerFactory factory) { throw new UnsupportedOperationException("Reactor Netty does not support multiple ports"); } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatReactiveWebServerFactoryTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/reactive/tomcat/TomcatReactiveWebServerFactoryTests.java similarity index 86% rename from spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatReactiveWebServerFactoryTests.java rename to spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/reactive/tomcat/TomcatReactiveWebServerFactoryTests.java index de9f9bde38..bee3d91ad7 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatReactiveWebServerFactoryTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/reactive/tomcat/TomcatReactiveWebServerFactoryTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.tomcat; +package org.springframework.boot.web.server.reactive.tomcat; import java.net.ConnectException; import java.time.Duration; @@ -38,11 +38,16 @@ import org.awaitility.Awaitility; import org.junit.jupiter.api.Test; import org.mockito.InOrder; -import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactory; -import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactoryTests; import org.springframework.boot.web.server.PortInUseException; import org.springframework.boot.web.server.Shutdown; import org.springframework.boot.web.server.WebServerException; +import org.springframework.boot.web.server.reactive.AbstractReactiveWebServerFactoryTests; +import org.springframework.boot.web.server.reactive.ConfigurableReactiveWebServerFactory; +import org.springframework.boot.web.server.tomcat.TomcatAccess; +import org.springframework.boot.web.server.tomcat.TomcatConnectorCustomizer; +import org.springframework.boot.web.server.tomcat.TomcatContextCustomizer; +import org.springframework.boot.web.server.tomcat.TomcatProtocolHandlerCustomizer; +import org.springframework.boot.web.server.tomcat.TomcatWebServer; import org.springframework.http.server.reactive.HttpHandler; import org.springframework.web.reactive.function.client.WebClient; @@ -74,7 +79,7 @@ class TomcatReactiveWebServerFactoryTests extends AbstractReactiveWebServerFacto TomcatReactiveWebServerFactory factory = getFactory(); TomcatContextCustomizer[] customizers = new TomcatContextCustomizer[4]; Arrays.setAll(customizers, (i) -> mock(TomcatContextCustomizer.class)); - factory.setTomcatContextCustomizers(Arrays.asList(customizers[0], customizers[1])); + factory.setContextCustomizers(Arrays.asList(customizers[0], customizers[1])); factory.addContextCustomizers(customizers[2], customizers[3]); this.webServer = factory.getWebServer(mock(HttpHandler.class)); InOrder ordered = inOrder((Object[]) customizers); @@ -128,8 +133,8 @@ class TomcatReactiveWebServerFactoryTests extends AbstractReactiveWebServerFacto @Test void setNullConnectorCustomizersShouldThrowException() { TomcatReactiveWebServerFactory factory = getFactory(); - assertThatIllegalArgumentException().isThrownBy(() -> factory.setTomcatConnectorCustomizers(null)) - .withMessageContaining("'tomcatConnectorCustomizers' must not be null"); + assertThatIllegalArgumentException().isThrownBy(() -> factory.setConnectorCustomizers(null)) + .withMessageContaining("'connectorCustomizers' must not be null"); } @Test @@ -137,14 +142,14 @@ class TomcatReactiveWebServerFactoryTests extends AbstractReactiveWebServerFacto TomcatReactiveWebServerFactory factory = getFactory(); assertThatIllegalArgumentException() .isThrownBy(() -> factory.addConnectorCustomizers((TomcatConnectorCustomizer[]) null)) - .withMessageContaining("'tomcatConnectorCustomizers' must not be null"); + .withMessageContaining("'connectorCustomizers' must not be null"); } @Test void setNullProtocolHandlerCustomizersShouldThrowException() { TomcatReactiveWebServerFactory factory = getFactory(); - assertThatIllegalArgumentException().isThrownBy(() -> factory.setTomcatProtocolHandlerCustomizers(null)) - .withMessageContaining("'tomcatProtocolHandlerCustomizers' must not be null"); + assertThatIllegalArgumentException().isThrownBy(() -> factory.setProtocolHandlerCustomizers(null)) + .withMessageContaining("'protocolHandlerCustomizers' must not be null"); } @Test @@ -152,7 +157,7 @@ class TomcatReactiveWebServerFactoryTests extends AbstractReactiveWebServerFacto TomcatReactiveWebServerFactory factory = getFactory(); assertThatIllegalArgumentException() .isThrownBy(() -> factory.addProtocolHandlerCustomizers((TomcatProtocolHandlerCustomizer[]) null)) - .withMessageContaining("'tomcatProtocolHandlerCustomizers' must not be null"); + .withMessageContaining("'protocolHandlerCustomizers' must not be null"); } @Test @@ -161,7 +166,7 @@ class TomcatReactiveWebServerFactoryTests extends AbstractReactiveWebServerFacto HttpHandler handler = mock(HttpHandler.class); TomcatConnectorCustomizer[] customizers = new TomcatConnectorCustomizer[4]; Arrays.setAll(customizers, (i) -> mock(TomcatConnectorCustomizer.class)); - factory.setTomcatConnectorCustomizers(Arrays.asList(customizers[0], customizers[1])); + factory.setConnectorCustomizers(Arrays.asList(customizers[0], customizers[1])); factory.addConnectorCustomizers(customizers[2], customizers[3]); this.webServer = factory.getWebServer(handler); InOrder ordered = inOrder((Object[]) customizers); @@ -177,7 +182,7 @@ class TomcatReactiveWebServerFactoryTests extends AbstractReactiveWebServerFacto HttpHandler handler = mock(HttpHandler.class); TomcatProtocolHandlerCustomizer>[] customizers = new TomcatProtocolHandlerCustomizer[4]; Arrays.setAll(customizers, (i) -> mock(TomcatProtocolHandlerCustomizer.class)); - factory.setTomcatProtocolHandlerCustomizers(Arrays.asList(customizers[0], customizers[1])); + factory.setProtocolHandlerCustomizers(Arrays.asList(customizers[0], customizers[1])); factory.addProtocolHandlerCustomizers(customizers[2], customizers[3]); this.webServer = factory.getWebServer(handler); InOrder ordered = inOrder((Object[]) customizers); @@ -191,16 +196,17 @@ class TomcatReactiveWebServerFactoryTests extends AbstractReactiveWebServerFacto TomcatReactiveWebServerFactory factory = getFactory(); Connector[] connectors = new Connector[4]; Arrays.setAll(connectors, (i) -> new Connector()); - factory.addAdditionalTomcatConnectors(connectors); + factory.addAdditionalConnectors(connectors); this.webServer = factory.getWebServer(mock(HttpHandler.class)); - Map connectorsByService = ((TomcatWebServer) this.webServer).getServiceConnectors(); + Map connectorsByService = TomcatAccess + .getServiceConnectors((TomcatWebServer) this.webServer); assertThat(connectorsByService.values().iterator().next()).hasSize(connectors.length + 1); } @Test void addNullAdditionalConnectorsThrows() { TomcatReactiveWebServerFactory factory = getFactory(); - assertThatIllegalArgumentException().isThrownBy(() -> factory.addAdditionalTomcatConnectors((Connector[]) null)) + assertThatIllegalArgumentException().isThrownBy(() -> factory.addAdditionalConnectors((Connector[]) null)) .withMessageContaining("'connectors' must not be null"); } @@ -227,7 +233,7 @@ class TomcatReactiveWebServerFactoryTests extends AbstractReactiveWebServerFacto @Test void portClashOfPrimaryConnectorResultsInPortInUseException() throws Exception { doWithBlockedPort((port) -> assertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> { - AbstractReactiveWebServerFactory factory = getFactory(); + TomcatReactiveWebServerFactory factory = getFactory(); factory.setPort(port); this.webServer = factory.getWebServer(mock(HttpHandler.class)); this.webServer.start(); @@ -284,14 +290,14 @@ class TomcatReactiveWebServerFactoryTests extends AbstractReactiveWebServerFacto @Override protected String startedLogMessage() { - return ((TomcatWebServer) this.webServer).getStartedLogMessage(); + return TomcatAccess.getStartedLogMessage((TomcatWebServer) this.webServer); } @Override - protected void addConnector(int port, AbstractReactiveWebServerFactory factory) { + protected void addConnector(int port, ConfigurableReactiveWebServerFactory factory) { Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol"); connector.setPort(port); - ((TomcatReactiveWebServerFactory) factory).addAdditionalTomcatConnectors(connector); + ((TomcatReactiveWebServerFactory) factory).addAdditionalConnectors(connector); } } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/UndertowReactiveWebServerFactoryTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/reactive/undertow/UndertowReactiveWebServerFactoryTests.java similarity index 90% rename from spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/UndertowReactiveWebServerFactoryTests.java rename to spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/reactive/undertow/UndertowReactiveWebServerFactoryTests.java index 0625ff8952..832b6f7825 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/UndertowReactiveWebServerFactoryTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/reactive/undertow/UndertowReactiveWebServerFactoryTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.undertow; +package org.springframework.boot.web.server.reactive.undertow; import java.io.File; import java.time.Duration; @@ -27,9 +27,12 @@ import org.junit.jupiter.api.io.TempDir; import org.mockito.InOrder; import reactor.core.publisher.Mono; -import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactory; -import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactoryTests; import org.springframework.boot.web.server.Shutdown; +import org.springframework.boot.web.server.reactive.AbstractReactiveWebServerFactoryTests; +import org.springframework.boot.web.server.reactive.ConfigurableReactiveWebServerFactory; +import org.springframework.boot.web.server.undertow.UndertowAccess; +import org.springframework.boot.web.server.undertow.UndertowBuilderCustomizer; +import org.springframework.boot.web.server.undertow.UndertowWebServer; import org.springframework.http.MediaType; import org.springframework.http.server.reactive.HttpHandler; import org.springframework.web.reactive.function.BodyInserters; @@ -158,11 +161,11 @@ class UndertowReactiveWebServerFactoryTests extends AbstractReactiveWebServerFac @Override protected String startedLogMessage() { - return ((UndertowWebServer) this.webServer).getStartLogMessage(); + return UndertowAccess.getStartedLogMessage((UndertowWebServer) this.webServer); } @Override - protected void addConnector(int port, AbstractReactiveWebServerFactory factory) { + protected void addConnector(int port, ConfigurableReactiveWebServerFactory factory) { ((UndertowReactiveWebServerFactory) factory) .addBuilderCustomizers((builder) -> builder.addHttpListener(port, "0.0.0.0")); } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/AbstractServletWebServerFactoryTests.java similarity index 89% rename from spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java rename to spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/AbstractServletWebServerFactoryTests.java index 4546b4b863..7e7c25d4ad 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/AbstractServletWebServerFactoryTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.servlet.server; +package org.springframework.boot.web.server.servlet; import java.io.File; import java.io.FileWriter; @@ -128,7 +128,6 @@ import org.springframework.boot.testsupport.classpath.resources.ResourcePath; import org.springframework.boot.testsupport.classpath.resources.WithPackageResources; import org.springframework.boot.testsupport.system.CapturedOutput; import org.springframework.boot.testsupport.system.OutputCaptureExtension; -import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories; import org.springframework.boot.testsupport.web.servlet.ExampleFilter; import org.springframework.boot.testsupport.web.servlet.ExampleServlet; import org.springframework.boot.web.server.Compression; @@ -143,10 +142,9 @@ import org.springframework.boot.web.server.Ssl; import org.springframework.boot.web.server.Ssl.ClientAuth; import org.springframework.boot.web.server.WebServer; import org.springframework.boot.web.server.WebServerException; +import org.springframework.boot.web.server.servlet.Session.SessionTrackingMode; import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.boot.web.servlet.ServletRegistrationBean; -import org.springframework.boot.web.servlet.server.Session.SessionTrackingMode; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; import org.springframework.http.HttpMethod; @@ -172,7 +170,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; /** - * Base for testing classes that extends {@link AbstractServletWebServerFactory}. + * Base for testing classes that implements {@link ConfigurableServletWebServerFactory}. * * @author Phillip Webb * @author Greg Turnquist @@ -182,7 +180,7 @@ import static org.mockito.Mockito.never; * @author Moritz Halbritter */ @ExtendWith(OutputCaptureExtension.class) -@DirtiesUrlFactories +// @DirtiesUrlFactories public abstract class AbstractServletWebServerFactoryTests { @TempDir @@ -215,7 +213,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void startServlet() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); this.webServer = factory.getWebServer(exampleServletRegistration()); this.webServer.start(); assertThat(getResponse(getLocalUrl("/hello"))).isEqualTo("Hello World"); @@ -223,7 +221,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void startCalledTwice(CapturedOutput output) throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); this.webServer = factory.getWebServer(exampleServletRegistration()); this.webServer.start(); int port = this.webServer.getPort(); @@ -235,7 +233,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void stopCalledTwice() { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); this.webServer = factory.getWebServer(exampleServletRegistration()); this.webServer.start(); this.webServer.stop(); @@ -244,7 +242,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test protected void restartAfterStop() throws IOException, URISyntaxException { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); this.webServer = factory.getWebServer(exampleServletRegistration()); this.webServer.start(); assertThat(getResponse(getLocalUrl("/hello"))).isEqualTo("Hello World"); @@ -257,7 +255,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void emptyServerWhenPortIsMinusOne() { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.setPort(-1); this.webServer = factory.getWebServer(exampleServletRegistration()); this.webServer.start(); @@ -266,7 +264,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void stopServlet() { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); this.webServer = factory.getWebServer(exampleServletRegistration()); this.webServer.start(); int port = this.webServer.getPort(); @@ -276,7 +274,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void startServletAndFilter() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); this.webServer = factory.getWebServer(exampleServletRegistration(), new FilterRegistrationBean<>(new ExampleFilter())); this.webServer.start(); @@ -285,7 +283,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void startBlocksUntilReadyToServe() { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); final Date[] date = new Date[1]; this.webServer = factory.getWebServer((servletContext) -> { try { @@ -302,7 +300,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void loadOnStartAfterContextIsInitialized() { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); final InitCountingServlet servlet = new InitCountingServlet(); this.webServer = factory .getWebServer((servletContext) -> servletContext.addServlet("test", servlet).setLoadOnStartup(1)); @@ -313,7 +311,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void portIsMinusOneWhenConnectionIsClosed() { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); this.webServer = factory.getWebServer(); this.webServer.start(); assertThat(this.webServer.getPort()).isGreaterThan(0); @@ -323,7 +321,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void specificPort() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); int specificPort = doWithRetry(() -> { factory.setPort(0); this.webServer = factory.getWebServer(exampleServletRegistration()); @@ -336,7 +334,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void specificContextRoot() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.setContextPath("/say"); this.webServer = factory.getWebServer(exampleServletRegistration()); this.webServer.start(); @@ -345,7 +343,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void contextPathIsLoggedOnStartup(CapturedOutput output) { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.setContextPath("/custom"); this.webServer = factory.getWebServer(exampleServletRegistration()); this.webServer.start(); @@ -355,24 +353,24 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void contextPathMustStartWithSlash() { assertThatIllegalArgumentException().isThrownBy(() -> getFactory().setContextPath("missingslash")) - .withMessageContaining("ContextPath must start with '/' and not end with '/'"); + .withMessageContaining("Context path must start with '/' and not end with '/'"); } @Test void contextPathMustNotEndWithSlash() { assertThatIllegalArgumentException().isThrownBy(() -> getFactory().setContextPath("extraslash/")) - .withMessageContaining("ContextPath must start with '/' and not end with '/'"); + .withMessageContaining("Context path must start with '/' and not end with '/'"); } @Test void contextRootPathMustNotBeSlash() { assertThatIllegalArgumentException().isThrownBy(() -> getFactory().setContextPath("/")) - .withMessageContaining("Root ContextPath must be specified using an empty string"); + .withMessageContaining("Root context path must be specified using an empty string"); } @Test void multipleConfigurations() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); ServletContextInitializer[] initializers = new ServletContextInitializer[6]; Arrays.setAll(initializers, (i) -> mock(ServletContextInitializer.class)); factory.setInitializers(Arrays.asList(initializers[2], initializers[3])); @@ -387,7 +385,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void documentRoot() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); addTestTxtFile(factory); this.webServer = factory.getWebServer(); this.webServer.start(); @@ -397,7 +395,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void mimeType() throws Exception { FileCopyUtils.copy("test", new FileWriter(new File(this.tempDir, "test.xxcss"))); - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.setRegisterDefaultServlet(true); factory.setDocumentRoot(this.tempDir); MimeMappings mimeMappings = new MimeMappings(); @@ -412,7 +410,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void errorPage() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.addErrorPages(new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/hello")); this.webServer = factory.getWebServer(exampleServletRegistration(), errorServletRegistration()); this.webServer.start(); @@ -422,7 +420,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void errorPageFromPutRequest() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.addErrorPages(new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/hello")); this.webServer = factory.getWebServer(exampleServletRegistration(), errorServletRegistration()); this.webServer.start(); @@ -445,7 +443,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test @WithPackageResources("test.jks") void sslDisabled() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); Ssl ssl = getSsl(null, "password", "classpath:test.jks"); ssl.setEnabled(false); factory.setSsl(ssl); @@ -460,7 +458,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test @WithPackageResources("test.jks") void sslGetScheme() throws Exception { // gh-2232 - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.setSsl(getSsl(null, "password", "classpath:test.jks")); this.webServer = factory.getWebServer(new ServletRegistrationBean<>(new ExampleServlet(true, false), "/hello")); this.webServer.start(); @@ -472,7 +470,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test @WithPackageResources("test.jks") void sslKeyAlias() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); Ssl ssl = getSsl(null, "password", "test-alias", "classpath:test.jks"); factory.setSsl(ssl); ServletRegistrationBean registration = new ServletRegistrationBean<>( @@ -493,7 +491,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test @WithPackageResources("test.jks") void sslWithInvalidAliasFailsDuringStartup() { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); Ssl ssl = getSsl(null, "password", "test-alias-404", "classpath:test.jks"); factory.setSsl(ssl); ServletRegistrationBean registration = new ServletRegistrationBean<>( @@ -510,7 +508,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test @WithPackageResources("test.jks") void serverHeaderIsDisabledByDefaultWhenUsingSsl() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.setSsl(getSsl(null, "password", "classpath:test.jks")); this.webServer = factory.getWebServer(new ServletRegistrationBean<>(new ExampleServlet(true, false), "/hello")); this.webServer.start(); @@ -526,7 +524,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test @WithPackageResources("test.jks") void serverHeaderCanBeCustomizedWhenUsingSsl() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.setServerHeader("MyServer"); factory.setSsl(getSsl(null, "password", "classpath:test.jks")); this.webServer = factory.getWebServer(new ServletRegistrationBean<>(new ExampleServlet(true, false), "/hello")); @@ -541,7 +539,7 @@ public abstract class AbstractServletWebServerFactoryTests { } protected final void testBasicSslWithKeyStore(String keyStore) throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); addTestTxtFile(factory); factory.setSsl(getSsl(null, "password", keyStore)); this.webServer = factory.getWebServer(); @@ -554,7 +552,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test @WithPackageResources("test.p12") void pkcs12KeyStoreAndTrustStore(@ResourcePath("test.p12") File keyStoreFile) throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); addTestTxtFile(factory); factory.setSsl(getSsl(ClientAuth.NEED, null, "classpath:test.p12", "classpath:test.p12", null, null)); this.webServer = factory.getWebServer(); @@ -572,7 +570,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test @WithPackageResources({ "test.p12", "test-cert.pem", "test-key.pem" }) void pemKeyStoreAndTrustStore(@ResourcePath("test.p12") File keyStoreFile) throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); addTestTxtFile(factory); factory.setSsl(getSsl("classpath:test-cert.pem", "classpath:test-key.pem")); this.webServer = factory.getWebServer(); @@ -590,7 +588,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test @WithPackageResources("test.p12") void pkcs12KeyStoreAndTrustStoreFromBundle(@ResourcePath("test.p12") File keyStoreFile) throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); addTestTxtFile(factory); factory.setSsl(Ssl.forBundle("test")); factory.setSslBundles( @@ -610,7 +608,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test @WithPackageResources({ "test.p12", "test-cert.pem", "test-key.pem" }) void pemKeyStoreAndTrustStoreFromBundle(@ResourcePath("test.p12") File keyStoreFile) throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); addTestTxtFile(factory); factory.setSsl(Ssl.forBundle("test")); factory.setSslBundles(new DefaultSslBundleRegistry("test", @@ -631,7 +629,7 @@ public abstract class AbstractServletWebServerFactoryTests { @WithPackageResources("test.jks") void sslNeedsClientAuthenticationSucceedsWithClientCertificate(@ResourcePath("test.jks") File keyStoreFile) throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.setRegisterDefaultServlet(true); addTestTxtFile(factory); factory.setSsl(getSsl(ClientAuth.NEED, "password", "classpath:test.jks", "classpath:test.jks", null, null)); @@ -650,7 +648,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test @WithPackageResources("test.jks") void sslNeedsClientAuthenticationFailsWithoutClientCertificate() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); addTestTxtFile(factory); factory.setSsl(getSsl(ClientAuth.NEED, "password", "classpath:test.jks")); this.webServer = factory.getWebServer(); @@ -665,7 +663,7 @@ public abstract class AbstractServletWebServerFactoryTests { @WithPackageResources("test.jks") void sslWantsClientAuthenticationSucceedsWithClientCertificate(@ResourcePath("test.jks") File keyStoreFile) throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); addTestTxtFile(factory); factory .setSsl(getSsl(ClientAuth.WANT, "password", "classpath:test.jks", null, new String[] { "TLSv1.2" }, null)); @@ -684,7 +682,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test @WithPackageResources("test.jks") void sslWantsClientAuthenticationSucceedsWithoutClientCertificate() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); addTestTxtFile(factory); factory.setSsl(getSsl(ClientAuth.WANT, "password", "classpath:test.jks")); this.webServer = factory.getWebServer(); @@ -696,15 +694,15 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void disableJspServletRegistration() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); - factory.getJsp().setRegistered(false); + ConfigurableServletWebServerFactory factory = getFactory(); + factory.getSettings().getJsp().setRegistered(false); this.webServer = factory.getWebServer(); assertThat(getJspServlet()).isNull(); } @Test void cannotReadClassPathFiles() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); this.webServer = factory.getWebServer(exampleServletRegistration()); this.webServer.start(); ClientHttpResponse response = getClientResponse( @@ -796,13 +794,13 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void defaultSessionTimeout() { - assertThat(getFactory().getSession().getTimeout()).hasMinutes(30); + assertThat(getFactory().getSettings().getSession().getTimeout()).hasMinutes(30); } @Test void persistSession() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); - factory.getSession().setPersistent(true); + ConfigurableServletWebServerFactory factory = getFactory(); + factory.getSettings().getSession().setPersistent(true); this.webServer = factory.getWebServer(sessionServletRegistration()); this.webServer.start(); String s1 = getResponse(getLocalUrl("/session")); @@ -818,11 +816,11 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void persistSessionInSpecificSessionStoreDir() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); File sessionStoreDir = new File(this.tempDir, "sessions"); sessionStoreDir.mkdir(); - factory.getSession().setPersistent(true); - factory.getSession().setStoreDir(sessionStoreDir); + factory.getSettings().getSession().setPersistent(true); + factory.getSettings().getSession().setStoreDir(sessionStoreDir); this.webServer = factory.getWebServer(sessionServletRegistration()); this.webServer.start(); getResponse(getLocalUrl("/session")); @@ -833,41 +831,43 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void getValidSessionStoreWhenSessionStoreNotSet() { - AbstractServletWebServerFactory factory = getFactory(); - File dir = factory.getValidSessionStoreDir(false); + ConfigurableServletWebServerFactory factory = getFactory(); + File dir = factory.getSettings().getSession().getSessionStoreDirectory().getValidDirectory(false); assertThat(dir).hasName("servlet-sessions"); assertThat(dir).hasParent(new ApplicationTemp().getDir()); } @Test void getValidSessionStoreWhenSessionStoreIsRelative() { - AbstractServletWebServerFactory factory = getFactory(); - factory.getSession().setStoreDir(new File("sessions")); - File dir = factory.getValidSessionStoreDir(false); + ConfigurableServletWebServerFactory factory = getFactory(); + factory.getSettings().getSession().setStoreDir(new File("sessions")); + File dir = factory.getSettings().getSession().getSessionStoreDirectory().getValidDirectory(false); assertThat(dir).hasName("sessions"); assertThat(dir).hasParent(new ApplicationHome().getDir()); } @Test void getValidSessionStoreWhenSessionStoreReferencesFile() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); File file = new File(this.tempDir, "file"); file.createNewFile(); - factory.getSession().setStoreDir(file); - assertThatIllegalStateException().isThrownBy(() -> factory.getValidSessionStoreDir(false)) + factory.getSettings().getSession().setStoreDir(file); + assertThatIllegalStateException() + .isThrownBy(() -> factory.getSettings().getSession().getSessionStoreDirectory().getValidDirectory(false)) .withMessageContaining("points to a file"); } @Test void sessionCookieConfiguration() { - AbstractServletWebServerFactory factory = getFactory(); - factory.getSession().getCookie().setName("testname"); - factory.getSession().getCookie().setDomain("testdomain"); - factory.getSession().getCookie().setPath("/testpath"); - factory.getSession().getCookie().setHttpOnly(true); - factory.getSession().getCookie().setSecure(true); - factory.getSession().getCookie().setPartitioned(true); - factory.getSession().getCookie().setMaxAge(Duration.ofSeconds(60)); + ConfigurableServletWebServerFactory factory = getFactory(); + org.springframework.boot.web.server.Cookie cookie = factory.getSettings().getSession().getCookie(); + cookie.setName("testname"); + cookie.setDomain("testdomain"); + cookie.setPath("/testpath"); + cookie.setHttpOnly(true); + cookie.setSecure(true); + cookie.setPartitioned(true); + cookie.setMaxAge(Duration.ofSeconds(60)); final AtomicReference configReference = new AtomicReference<>(); this.webServer = factory.getWebServer((context) -> configReference.set(context.getSessionCookieConfig())); SessionCookieConfig sessionCookieConfig = configReference.get(); @@ -883,8 +883,8 @@ public abstract class AbstractServletWebServerFactoryTests { @ParameterizedTest @EnumSource(mode = EnumSource.Mode.EXCLUDE, names = "OMITTED") void sessionCookieSameSiteAttributeCanBeConfiguredAndOnlyAffectsSessionCookies(SameSite sameSite) throws Exception { - AbstractServletWebServerFactory factory = getFactory(); - factory.getSession().getCookie().setSameSite(sameSite); + ConfigurableServletWebServerFactory factory = getFactory(); + factory.getSettings().getSession().getCookie().setSameSite(sameSite); factory.addInitializers(new ServletRegistrationBean<>(new CookieServlet(false), "/")); this.webServer = factory.getWebServer(); this.webServer.start(); @@ -899,9 +899,9 @@ public abstract class AbstractServletWebServerFactoryTests { @EnumSource(mode = EnumSource.Mode.EXCLUDE, names = "OMITTED") void sessionCookieSameSiteAttributeCanBeConfiguredAndOnlyAffectsSessionCookiesWhenUsingCustomName(SameSite sameSite) throws Exception { - AbstractServletWebServerFactory factory = getFactory(); - factory.getSession().getCookie().setName("THESESSION"); - factory.getSession().getCookie().setSameSite(sameSite); + ConfigurableServletWebServerFactory factory = getFactory(); + factory.getSettings().getSession().getCookie().setName("THESESSION"); + factory.getSettings().getSession().getCookie().setSameSite(sameSite); factory.addInitializers(new ServletRegistrationBean<>(new CookieServlet(false), "/")); this.webServer = factory.getWebServer(); this.webServer.start(); @@ -914,7 +914,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void cookieSameSiteSuppliers() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.addCookieSameSiteSuppliers(CookieSameSiteSupplier.ofLax().whenHasName("relaxed")); factory.addCookieSameSiteSuppliers(CookieSameSiteSupplier.ofNone().whenHasName("empty")); factory.addCookieSameSiteSuppliers(CookieSameSiteSupplier.ofStrict().whenHasName("controlled")); @@ -934,9 +934,9 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void cookieSameSiteSuppliersShouldNotAffectSessionCookie() throws IOException, URISyntaxException { - AbstractServletWebServerFactory factory = getFactory(); - factory.getSession().getCookie().setSameSite(SameSite.LAX); - factory.getSession().getCookie().setName("SESSIONCOOKIE"); + ConfigurableServletWebServerFactory factory = getFactory(); + factory.getSettings().getSession().getCookie().setSameSite(SameSite.LAX); + factory.getSettings().getSession().getCookie().setName("SESSIONCOOKIE"); factory.addCookieSameSiteSuppliers(CookieSameSiteSupplier.ofStrict()); factory.addInitializers(new ServletRegistrationBean<>(new CookieServlet(false), "/")); this.webServer = factory.getWebServer(); @@ -951,9 +951,9 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void cookieSameSiteSuppliersShouldNotAffectOmittedSameSite() throws IOException, URISyntaxException { - AbstractServletWebServerFactory factory = getFactory(); - factory.getSession().getCookie().setSameSite(SameSite.OMITTED); - factory.getSession().getCookie().setName("SESSIONCOOKIE"); + ConfigurableServletWebServerFactory factory = getFactory(); + factory.getSettings().getSession().getCookie().setSameSite(SameSite.OMITTED); + factory.getSettings().getSession().getCookie().setName("SESSIONCOOKIE"); factory.addCookieSameSiteSuppliers(CookieSameSiteSupplier.ofStrict()); factory.addInitializers(new ServletRegistrationBean<>(new CookieServlet(false), "/")); this.webServer = factory.getWebServer(); @@ -968,13 +968,13 @@ public abstract class AbstractServletWebServerFactoryTests { @Test protected void sslSessionTracking() { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); Ssl ssl = new Ssl(); ssl.setEnabled(true); ssl.setKeyStore("src/test/resources/org/springframework/boot/web/server/test.jks"); ssl.setKeyPassword("password"); factory.setSsl(ssl); - factory.getSession().setTrackingModes(EnumSet.of(SessionTrackingMode.SSL)); + factory.getSettings().getSession().setTrackingModes(EnumSet.of(SessionTrackingMode.SSL)); AtomicReference contextReference = new AtomicReference<>(); this.webServer = factory.getWebServer(contextReference::set); assertThat(contextReference.get().getEffectiveSessionTrackingModes()) @@ -1009,7 +1009,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void compressionWithoutContentSizeHeader() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); Compression compression = new Compression(); compression.setEnabled(true); factory.setCompression(compression); @@ -1025,7 +1025,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void mimeMappingsAreCorrectlyConfigured() { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); this.webServer = factory.getWebServer(); Collection configuredMimeMappings = getActualMimeMappings().entrySet() .stream() @@ -1037,7 +1037,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void additionalMimeMappingsCanBeConfigured() { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); MimeMappings additionalMimeMappings = new MimeMappings(); additionalMimeMappings.add("a", "alpha"); additionalMimeMappings.add("b", "bravo"); @@ -1054,7 +1054,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void rootServletContextResource() { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); final AtomicReference rootResource = new AtomicReference<>(); this.webServer = factory.getWebServer((servletContext) -> { try { @@ -1070,7 +1070,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void customServerHeader() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.setServerHeader("MyServer"); this.webServer = factory.getWebServer(exampleServletRegistration()); this.webServer.start(); @@ -1080,7 +1080,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void serverHeaderIsDisabledByDefault() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); this.webServer = factory.getWebServer(exampleServletRegistration()); this.webServer.start(); ClientHttpResponse response = getClientResponse(getLocalUrl("/hello")); @@ -1091,7 +1091,7 @@ public abstract class AbstractServletWebServerFactoryTests { protected void portClashOfPrimaryConnectorResultsInPortInUseException() throws Exception { doWithBlockedPort((port) -> { assertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.setPort(port); AbstractServletWebServerFactoryTests.this.webServer = factory.getWebServer(); AbstractServletWebServerFactoryTests.this.webServer.start(); @@ -1103,7 +1103,7 @@ public abstract class AbstractServletWebServerFactoryTests { protected void portClashOfSecondaryConnectorResultsInPortInUseException() throws Exception { doWithBlockedPort((port) -> { assertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); addConnector(port, factory); AbstractServletWebServerFactoryTests.this.webServer = factory.getWebServer(); AbstractServletWebServerFactoryTests.this.webServer.start(); @@ -1113,7 +1113,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void malformedAddress() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.setAddress(InetAddress.getByName("129.129.129.129")); assertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> { this.webServer = factory.getWebServer(); @@ -1123,7 +1123,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void localeCharsetMappingsAreConfigured() { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); Map mappings = new HashMap<>(); mappings.put(Locale.GERMAN, StandardCharsets.UTF_8); factory.setLocaleCharsetMappings(mappings); @@ -1136,8 +1136,8 @@ public abstract class AbstractServletWebServerFactoryTests { void jspServletInitParameters() throws Exception { Map initParameters = new HashMap<>(); initParameters.put("a", "alpha"); - AbstractServletWebServerFactory factory = getFactory(); - factory.getJsp().setInitParameters(initParameters); + ConfigurableServletWebServerFactory factory = getFactory(); + factory.getSettings().getJsp().setInitParameters(initParameters); this.webServer = factory.getWebServer(); Assumptions.assumeFalse(getJspServlet() == null); JspServlet jspServlet = getJspServlet(); @@ -1146,7 +1146,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void jspServletIsNotInDevelopmentModeByDefault() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); this.webServer = factory.getWebServer(); Assumptions.assumeFalse(getJspServlet() == null); JspServlet jspServlet = getJspServlet(); @@ -1156,7 +1156,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void faultyFilterCausesStartFailure() { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.addInitializers((servletContext) -> servletContext.addFilter("faulty", new Filter() { @Override @@ -1180,28 +1180,31 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void sessionConfiguration() { - AbstractServletWebServerFactory factory = getFactory(); - factory.getSession().setTimeout(Duration.ofSeconds(123)); - factory.getSession().setTrackingModes(EnumSet.of(SessionTrackingMode.COOKIE, SessionTrackingMode.URL)); - factory.getSession().getCookie().setName("testname"); - factory.getSession().getCookie().setDomain("testdomain"); - factory.getSession().getCookie().setPath("/testpath"); - factory.getSession().getCookie().setHttpOnly(true); - factory.getSession().getCookie().setSecure(true); - factory.getSession().getCookie().setPartitioned(false); - factory.getSession().getCookie().setMaxAge(Duration.ofMinutes(1)); + ConfigurableServletWebServerFactory factory = getFactory(); + Session session = factory.getSettings().getSession(); + session.setTimeout(Duration.ofSeconds(123)); + session.setTrackingModes(EnumSet.of(SessionTrackingMode.COOKIE, SessionTrackingMode.URL)); + org.springframework.boot.web.server.Cookie cookie = session.getCookie(); + cookie.setName("testname"); + cookie.setDomain("testdomain"); + cookie.setPath("/testpath"); + cookie.setHttpOnly(true); + cookie.setSecure(true); + cookie.setPartitioned(false); + cookie.setMaxAge(Duration.ofMinutes(1)); AtomicReference contextReference = new AtomicReference<>(); factory.getWebServer(contextReference::set).start(); ServletContext servletContext = contextReference.get(); assertThat(servletContext.getEffectiveSessionTrackingModes()) .isEqualTo(EnumSet.of(jakarta.servlet.SessionTrackingMode.COOKIE, jakarta.servlet.SessionTrackingMode.URL)); - assertThat(servletContext.getSessionCookieConfig().getName()).isEqualTo("testname"); - assertThat(servletContext.getSessionCookieConfig().getDomain()).isEqualTo("testdomain"); - assertThat(servletContext.getSessionCookieConfig().getPath()).isEqualTo("/testpath"); - assertThat(servletContext.getSessionCookieConfig().isHttpOnly()).isTrue(); - assertThat(servletContext.getSessionCookieConfig().isSecure()).isTrue(); - assertThat(servletContext.getSessionCookieConfig().getMaxAge()).isEqualTo(60); - assertThat(servletContext.getSessionCookieConfig().getAttribute("Partitioned")).isEqualTo("false"); + SessionCookieConfig sessionCookieConfig = servletContext.getSessionCookieConfig(); + assertThat(sessionCookieConfig.getName()).isEqualTo("testname"); + assertThat(sessionCookieConfig.getDomain()).isEqualTo("testdomain"); + assertThat(sessionCookieConfig.getPath()).isEqualTo("/testpath"); + assertThat(sessionCookieConfig.isHttpOnly()).isTrue(); + assertThat(sessionCookieConfig.isSecure()).isTrue(); + assertThat(sessionCookieConfig.getMaxAge()).isEqualTo(60); + assertThat(sessionCookieConfig.getAttribute("Partitioned")).isEqualTo("false"); } @Test @@ -1224,7 +1227,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void exceptionThrownOnLoadFailureIsRethrown() { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); this.webServer = factory .getWebServer((context) -> context.addServlet("failing", FailingServlet.class).setLoadOnStartup(0)); assertThatExceptionOfType(WebServerException.class).isThrownBy(this.webServer::start) @@ -1233,7 +1236,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void whenThereAreNoInFlightRequestsShutDownGracefullyInvokesCallbackWithIdle() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.setShutdown(Shutdown.GRACEFUL); this.webServer = factory.getWebServer(); this.webServer.start(); @@ -1245,7 +1248,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void whenARequestRemainsInFlightThenShutDownGracefullyDoesNotInvokeCallbackUntilTheRequestCompletes() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.setShutdown(Shutdown.GRACEFUL); BlockingServlet blockingServlet = new BlockingServlet(); this.webServer = factory.getWebServer((context) -> { @@ -1266,7 +1269,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void whenAnAsyncRequestRemainsInFlightThenShutDownGracefullyDoesNotInvokeCallbackUntilRequestCompletes() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.setShutdown(Shutdown.GRACEFUL); BlockingAsyncServlet blockingAsyncServlet = new BlockingAsyncServlet(); this.webServer = factory.getWebServer((context) -> { @@ -1290,7 +1293,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void whenARequestIsActiveThenStopWillComplete() throws InterruptedException { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); BlockingServlet blockingServlet = new BlockingServlet(); this.webServer = factory .getWebServer((context) -> context.addServlet("blockingServlet", blockingServlet).addMapping("/")); @@ -1309,7 +1312,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test protected void whenHttp2IsEnabledAndSslIsDisabledThenH2cCanBeUsed() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); Http2 http2 = new Http2(); http2.setEnabled(true); factory.setHttp2(http2); @@ -1326,7 +1329,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test protected void whenHttp2IsEnabledAndSslIsDisabledThenHttp11CanStillBeUsed() throws IOException, URISyntaxException { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); Http2 http2 = new Http2(); http2.setEnabled(true); factory.setHttp2(http2); @@ -1337,7 +1340,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void whenARequestIsActiveAfterGracefulShutdownEndsThenStopWillComplete() throws InterruptedException { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.setShutdown(Shutdown.GRACEFUL); BlockingServlet blockingServlet = new BlockingServlet(); this.webServer = factory @@ -1361,7 +1364,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void startedLogMessageWithSinglePort() { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); this.webServer = factory.getWebServer(); this.webServer.start(); assertThat(startedLogMessage()).matches("(Jetty|Tomcat|Undertow) started on port " + this.webServer.getPort() @@ -1370,7 +1373,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void startedLogMessageWithSinglePortAndContextPath() { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.setContextPath("/test"); this.webServer = factory.getWebServer(); this.webServer.start(); @@ -1380,7 +1383,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void startedLogMessageWithMultiplePorts() { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); addConnector(0, factory); this.webServer = factory.getWebServer(); this.webServer.start(); @@ -1390,7 +1393,7 @@ public abstract class AbstractServletWebServerFactoryTests { @Test void servletComponentsAreInitializedWithTheSameThreadContextClassLoader() { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); ThreadContextClassLoaderCapturingServlet servlet = new ThreadContextClassLoaderCapturingServlet(); ThreadContextClassLoaderCapturingFilter filter = new ThreadContextClassLoaderCapturingFilter(); ThreadContextClassLoaderCapturingListener listener = new ThreadContextClassLoaderCapturingListener(); @@ -1440,7 +1443,7 @@ public abstract class AbstractServletWebServerFactoryTests { fail("Exception did not wrap FailingServletException"); } - protected abstract void addConnector(int port, AbstractServletWebServerFactory factory); + protected abstract void addConnector(int port, ConfigurableServletWebServerFactory factory); protected abstract void handleExceptionCausedByBlockedPortOnPrimaryConnector(RuntimeException ex, int blockedPort); @@ -1471,7 +1474,7 @@ public abstract class AbstractServletWebServerFactoryTests { char[] chars = new char[contentSize]; Arrays.fill(chars, 'F'); String testContent = new String(chars); - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); Compression compression = new Compression(); compression.setEnabled(true); if (mimeTypes != null) { @@ -1501,7 +1504,7 @@ public abstract class AbstractServletWebServerFactoryTests { protected abstract Charset getCharset(Locale locale); - protected void addTestTxtFile(AbstractServletWebServerFactory factory) throws IOException { + protected void addTestTxtFile(ConfigurableServletWebServerFactory factory) throws IOException { FileCopyUtils.copy("test", new FileWriter(new File(this.tempDir, "test.txt"))); factory.setDocumentRoot(this.tempDir); factory.setRegisterDefaultServlet(true); @@ -1578,7 +1581,7 @@ public abstract class AbstractServletWebServerFactoryTests { .contains("remoteaddr=140.211.11.130"); } - protected abstract AbstractServletWebServerFactory getFactory(); + protected abstract ConfigurableServletWebServerFactory getFactory(); protected abstract org.apache.jasper.servlet.JspServlet getJspServlet() throws Exception; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/CookieSameSiteSupplierTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/CookieSameSiteSupplierTests.java similarity index 99% rename from spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/CookieSameSiteSupplierTests.java rename to spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/CookieSameSiteSupplierTests.java index a5a8b3fe3b..ea63fdaa3e 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/CookieSameSiteSupplierTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/CookieSameSiteSupplierTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.servlet.server; +package org.springframework.boot.web.server.servlet; import java.util.function.Supplier; import java.util.regex.Pattern; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/DocumentRootTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/DocumentRootTests.java similarity index 95% rename from spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/DocumentRootTests.java rename to spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/DocumentRootTests.java index 6dc933a2a4..820a41cc6e 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/DocumentRootTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/DocumentRootTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.servlet.server; +package org.springframework.boot.web.server.servlet; import java.io.File; import java.net.URL; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/StaticResourceJarsTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/StaticResourceJarsTests.java similarity index 98% rename from spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/StaticResourceJarsTests.java rename to spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/StaticResourceJarsTests.java index 050cbb4477..fd29af04c1 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/StaticResourceJarsTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/StaticResourceJarsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.servlet.server; +package org.springframework.boot.web.server.servlet; import java.io.File; import java.io.FileOutputStream; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactoryTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/jetty/JettyServletWebServerFactoryTests.java similarity index 95% rename from spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactoryTests.java rename to spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/jetty/JettyServletWebServerFactoryTests.java index 681e5d8d5c..14c0e3946d 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactoryTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/jetty/JettyServletWebServerFactoryTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.jetty; +package org.springframework.boot.web.server.servlet.jetty; import java.lang.reflect.Method; import java.net.InetAddress; @@ -72,8 +72,11 @@ import org.springframework.boot.web.server.Shutdown; import org.springframework.boot.web.server.Ssl; import org.springframework.boot.web.server.Ssl.ServerNameSslBundle; import org.springframework.boot.web.server.WebServerException; -import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactory; -import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactoryTests; +import org.springframework.boot.web.server.jetty.JettyAccess; +import org.springframework.boot.web.server.jetty.JettyServerCustomizer; +import org.springframework.boot.web.server.jetty.JettyWebServer; +import org.springframework.boot.web.server.servlet.AbstractServletWebServerFactoryTests; +import org.springframework.boot.web.server.servlet.ConfigurableServletWebServerFactory; import org.springframework.util.ReflectionUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -111,7 +114,7 @@ class JettyServletWebServerFactoryTests extends AbstractServletWebServerFactoryT } @Override - protected void addConnector(int port, AbstractServletWebServerFactory factory) { + protected void addConnector(int port, ConfigurableServletWebServerFactory factory) { ((JettyServletWebServerFactory) factory).addServerCustomizers((server) -> { ServerConnector connector = new ServerConnector(server); connector.setPort(port); @@ -170,7 +173,7 @@ class JettyServletWebServerFactoryTests extends AbstractServletWebServerFactoryT @Test void contextPathIsLoggedOnStartupWhenCompressionIsEnabled(CapturedOutput output) { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.setContextPath("/custom"); Compression compression = new Compression(); compression.setEnabled(true); @@ -219,15 +222,15 @@ class JettyServletWebServerFactoryTests extends AbstractServletWebServerFactoryT @Test void sessionTimeout() { - JettyServletWebServerFactory factory = getFactory(); - factory.getSession().setTimeout(Duration.ofSeconds(10)); + ConfigurableServletWebServerFactory factory = getFactory(); + factory.getSettings().getSession().setTimeout(Duration.ofSeconds(10)); assertTimeout(factory, 10); } @Test void sessionTimeoutInMinutes() { - JettyServletWebServerFactory factory = getFactory(); - factory.getSession().setTimeout(Duration.ofMinutes(1)); + ConfigurableServletWebServerFactory factory = getFactory(); + factory.getSettings().getSession().setTimeout(Duration.ofMinutes(1)); assertTimeout(factory, 60); } @@ -317,7 +320,7 @@ class JettyServletWebServerFactoryTests extends AbstractServletWebServerFactoryT @Test void whenServerIsShuttingDownGracefullyThenNewConnectionsCannotBeMade() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.setShutdown(Shutdown.GRACEFUL); BlockingServlet blockingServlet = new BlockingServlet(); this.webServer = factory.getWebServer((context) -> { @@ -342,7 +345,7 @@ class JettyServletWebServerFactoryTests extends AbstractServletWebServerFactoryT @Test void whenServerIsShuttingDownGracefullyThenResponseToRequestOnIdleConnectionWillHaveAConnectionCloseHeader() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.setShutdown(Shutdown.GRACEFUL); BlockingServlet blockingServlet = new BlockingServlet(); this.webServer = factory.getWebServer((context) -> { @@ -377,7 +380,7 @@ class JettyServletWebServerFactoryTests extends AbstractServletWebServerFactoryT @Test void whenARequestCompletesAfterGracefulShutdownHasBegunThenItHasAConnectionCloseHeader() throws InterruptedException, ExecutionException { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.setShutdown(Shutdown.GRACEFUL); BlockingServlet blockingServlet = new BlockingServlet(); this.webServer = factory.getWebServer((context) -> { @@ -408,7 +411,7 @@ class JettyServletWebServerFactoryTests extends AbstractServletWebServerFactoryT return ssl; } - private void assertTimeout(JettyServletWebServerFactory factory, int expected) { + private void assertTimeout(ConfigurableServletWebServerFactory factory, int expected) { this.webServer = factory.getWebServer(); JettyWebServer jettyWebServer = (JettyWebServer) this.webServer; WebAppContext webAppContext = findWebAppContext(jettyWebServer); @@ -582,7 +585,7 @@ class JettyServletWebServerFactoryTests extends AbstractServletWebServerFactoryT @Override protected String startedLogMessage() { - return ((JettyWebServer) this.webServer).getStartedLogMessage(); + return JettyAccess.getStartedLogMessage((JettyWebServer) this.webServer); } private WebAppContext findWebAppContext(JettyWebServer webServer) { diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/LoaderHidingResourceTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/jetty/LoaderHidingResourceTests.java similarity index 97% rename from spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/LoaderHidingResourceTests.java rename to spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/jetty/LoaderHidingResourceTests.java index b3b9669242..1f5bc5e697 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/LoaderHidingResourceTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/jetty/LoaderHidingResourceTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.jetty; +package org.springframework.boot.web.server.servlet.jetty; import java.io.File; import java.io.FileOutputStream; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TldPatternsTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/tomcat/TldPatternsTests.java similarity index 94% rename from spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TldPatternsTests.java rename to spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/tomcat/TldPatternsTests.java index 1041a59b0c..0720b5f2a2 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TldPatternsTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/tomcat/TldPatternsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.tomcat; +package org.springframework.boot.web.server.servlet.tomcat; import java.io.IOException; import java.io.InputStream; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactoryTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/tomcat/TomcatServletWebServerFactoryTests.java similarity index 91% rename from spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactoryTests.java rename to spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/tomcat/TomcatServletWebServerFactoryTests.java index 7f6bef418f..9fa52ddcfa 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactoryTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/tomcat/TomcatServletWebServerFactoryTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.tomcat; +package org.springframework.boot.web.server.servlet.tomcat; import java.io.File; import java.io.IOException; @@ -50,7 +50,6 @@ import org.apache.catalina.LifecycleEvent; import org.apache.catalina.LifecycleListener; import org.apache.catalina.LifecycleState; import org.apache.catalina.Service; -import org.apache.catalina.SessionIdGenerator; import org.apache.catalina.Valve; import org.apache.catalina.connector.Connector; import org.apache.catalina.core.AprLifecycleListener; @@ -77,7 +76,6 @@ import org.apache.tomcat.util.scan.StandardJarScanFilter; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.awaitility.Awaitility; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.mockito.InOrder; @@ -88,8 +86,15 @@ import org.springframework.boot.web.server.PortInUseException; import org.springframework.boot.web.server.Shutdown; import org.springframework.boot.web.server.Ssl; import org.springframework.boot.web.server.WebServerException; -import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactory; -import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactoryTests; +import org.springframework.boot.web.server.servlet.AbstractServletWebServerFactoryTests; +import org.springframework.boot.web.server.servlet.ConfigurableServletWebServerFactory; +import org.springframework.boot.web.server.tomcat.ConnectorStartFailedException; +import org.springframework.boot.web.server.tomcat.TomcatAccess; +import org.springframework.boot.web.server.tomcat.TomcatConnectorCustomizer; +import org.springframework.boot.web.server.tomcat.TomcatContextCustomizer; +import org.springframework.boot.web.server.tomcat.TomcatEmbeddedContext; +import org.springframework.boot.web.server.tomcat.TomcatProtocolHandlerCustomizer; +import org.springframework.boot.web.server.tomcat.TomcatWebServer; import org.springframework.core.io.ByteArrayResource; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.support.PropertiesLoaderUtils; @@ -185,7 +190,7 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory TomcatServletWebServerFactory factory = getFactory(); TomcatContextCustomizer[] customizers = new TomcatContextCustomizer[4]; Arrays.setAll(customizers, (i) -> mock(TomcatContextCustomizer.class)); - factory.setTomcatContextCustomizers(Arrays.asList(customizers[0], customizers[1])); + factory.setContextCustomizers(Arrays.asList(customizers[0], customizers[1])); factory.addContextCustomizers(customizers[2], customizers[3]); this.webServer = factory.getWebServer(); InOrder ordered = inOrder((Object[]) customizers); @@ -208,7 +213,7 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory TomcatServletWebServerFactory factory = getFactory(); TomcatConnectorCustomizer[] customizers = new TomcatConnectorCustomizer[4]; Arrays.setAll(customizers, (i) -> mock(TomcatConnectorCustomizer.class)); - factory.setTomcatConnectorCustomizers(Arrays.asList(customizers[0], customizers[1])); + factory.setConnectorCustomizers(Arrays.asList(customizers[0], customizers[1])); factory.addConnectorCustomizers(customizers[2], customizers[3]); this.webServer = factory.getWebServer(); InOrder ordered = inOrder((Object[]) customizers); @@ -223,7 +228,7 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory TomcatServletWebServerFactory factory = getFactory(); TomcatProtocolHandlerCustomizer>[] customizers = new TomcatProtocolHandlerCustomizer[4]; Arrays.setAll(customizers, (i) -> mock(TomcatProtocolHandlerCustomizer.class)); - factory.setTomcatProtocolHandlerCustomizers(Arrays.asList(customizers[0], customizers[1])); + factory.setProtocolHandlerCustomizers(Arrays.asList(customizers[0], customizers[1])); factory.addProtocolHandlerCustomizers(customizers[2], customizers[3]); this.webServer = factory.getWebServer(); InOrder ordered = inOrder((Object[]) customizers); @@ -239,7 +244,8 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory .setProcessorCache(250); factory.addProtocolHandlerCustomizers(customizer); Tomcat tomcat = getTomcat(factory); - Connector connector = ((TomcatWebServer) this.webServer).getServiceConnectors().get(tomcat.getService())[0]; + Connector connector = TomcatAccess.getServiceConnectors((TomcatWebServer) this.webServer) + .get(tomcat.getService())[0]; AbstractHttp11Protocol protocolHandler = (AbstractHttp11Protocol) connector.getProtocolHandler(); assertThat(protocolHandler.getProcessorCache()).isEqualTo(250); } @@ -253,10 +259,10 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory connector.setPort(0); return connector; }); - factory.addAdditionalTomcatConnectors(connectors); + factory.addAdditionalConnectors(connectors); this.webServer = factory.getWebServer(); Map connectorsByService = new HashMap<>( - ((TomcatWebServer) this.webServer).getServiceConnectors()); + TomcatAccess.getServiceConnectors((TomcatWebServer) this.webServer)); assertThat(connectorsByService.values().iterator().next()).hasSize(connectors.length + 1); this.webServer.start(); this.webServer.stop(); @@ -270,28 +276,28 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory @Test void addNullAdditionalConnectorThrows() { TomcatServletWebServerFactory factory = getFactory(); - assertThatIllegalArgumentException().isThrownBy(() -> factory.addAdditionalTomcatConnectors((Connector[]) null)) + assertThatIllegalArgumentException().isThrownBy(() -> factory.addAdditionalConnectors((Connector[]) null)) .withMessageContaining("'connectors' must not be null"); } @Test void sessionTimeout() { TomcatServletWebServerFactory factory = getFactory(); - factory.getSession().setTimeout(Duration.ofSeconds(10)); + factory.getSettings().getSession().setTimeout(Duration.ofSeconds(10)); assertTimeout(factory, 1); } @Test void sessionTimeoutInMinutes() { TomcatServletWebServerFactory factory = getFactory(); - factory.getSession().setTimeout(Duration.ofMinutes(1)); + factory.getSettings().getSession().setTimeout(Duration.ofMinutes(1)); assertTimeout(factory, 1); } @Test void noSessionTimeout() { TomcatServletWebServerFactory factory = getFactory(); - factory.getSession().setTimeout(null); + factory.getSettings().getSession().setTimeout(null); assertTimeout(factory, -1); } @@ -307,8 +313,8 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory @Test void setNullTomcatContextCustomizersThrows() { TomcatServletWebServerFactory factory = getFactory(); - assertThatIllegalArgumentException().isThrownBy(() -> factory.setTomcatContextCustomizers(null)) - .withMessageContaining("'tomcatContextCustomizers' must not be null"); + assertThatIllegalArgumentException().isThrownBy(() -> factory.setContextCustomizers(null)) + .withMessageContaining("'contextCustomizers' must not be null"); } @Test @@ -316,14 +322,14 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory TomcatServletWebServerFactory factory = getFactory(); assertThatIllegalArgumentException() .isThrownBy(() -> factory.addContextCustomizers((TomcatContextCustomizer[]) null)) - .withMessageContaining("'tomcatContextCustomizers' must not be null"); + .withMessageContaining("'contextCustomizers' must not be null"); } @Test void setNullTomcatConnectorCustomizersThrows() { TomcatServletWebServerFactory factory = getFactory(); - assertThatIllegalArgumentException().isThrownBy(() -> factory.setTomcatConnectorCustomizers(null)) - .withMessageContaining("'tomcatConnectorCustomizers' must not be null"); + assertThatIllegalArgumentException().isThrownBy(() -> factory.setConnectorCustomizers(null)) + .withMessageContaining("'connectorCustomizers' must not be null"); } @Test @@ -331,14 +337,14 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory TomcatServletWebServerFactory factory = getFactory(); assertThatIllegalArgumentException() .isThrownBy(() -> factory.addConnectorCustomizers((TomcatConnectorCustomizer[]) null)) - .withMessageContaining("'tomcatConnectorCustomizers' must not be null"); + .withMessageContaining("'connectorCustomizers' must not be null"); } @Test void setNullTomcatProtocolHandlerCustomizersThrows() { TomcatServletWebServerFactory factory = getFactory(); - assertThatIllegalArgumentException().isThrownBy(() -> factory.setTomcatProtocolHandlerCustomizers(null)) - .withMessageContaining("'tomcatProtocolHandlerCustomizer' must not be null"); + assertThatIllegalArgumentException().isThrownBy(() -> factory.setProtocolHandlerCustomizers(null)) + .withMessageContaining("'protocolHandlerCustomizers' must not be null"); } @Test @@ -346,7 +352,7 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory TomcatServletWebServerFactory factory = getFactory(); assertThatIllegalArgumentException() .isThrownBy(() -> factory.addProtocolHandlerCustomizers((TomcatProtocolHandlerCustomizer[]) null)) - .withMessageContaining("'tomcatProtocolHandlerCustomizers' must not be null"); + .withMessageContaining("'protocolHandlerCustomizers' must not be null"); } @Test @@ -354,7 +360,8 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory TomcatServletWebServerFactory factory = getFactory(); factory.setUriEncoding(StandardCharsets.US_ASCII); Tomcat tomcat = getTomcat(factory); - Connector connector = ((TomcatWebServer) this.webServer).getServiceConnectors().get(tomcat.getService())[0]; + Connector connector = TomcatAccess.getServiceConnectors((TomcatWebServer) this.webServer) + .get(tomcat.getService())[0]; assertThat(connector.getURIEncoding()).isEqualTo("US-ASCII"); } @@ -362,7 +369,8 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory void defaultUriEncoding() { TomcatServletWebServerFactory factory = getFactory(); Tomcat tomcat = getTomcat(factory); - Connector connector = ((TomcatWebServer) this.webServer).getServiceConnectors().get(tomcat.getService())[0]; + Connector connector = TomcatAccess.getServiceConnectors((TomcatWebServer) this.webServer) + .get(tomcat.getService())[0]; assertThat(connector.getURIEncoding()).isEqualTo("UTF-8"); } @@ -382,10 +390,10 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory } @Override - protected void addConnector(int port, AbstractServletWebServerFactory factory) { + protected void addConnector(int port, ConfigurableServletWebServerFactory factory) { Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol"); connector.setPort(port); - ((TomcatServletWebServerFactory) factory).addAdditionalTomcatConnectors(connector); + ((TomcatServletWebServerFactory) factory).addAdditionalConnectors(connector); } @Test @@ -449,25 +457,6 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory } } - @Test - @Disabled("See https://github.com/apache/tomcat/commit/c3e33b62101c5ee155808dd1932acde0cac65fe3") - void sessionIdGeneratorIsConfiguredWithAttributesFromTheManager() { - System.setProperty("jvmRoute", "test"); - try { - TomcatServletWebServerFactory factory = getFactory(); - this.webServer = factory.getWebServer(); - this.webServer.start(); - } - finally { - System.clearProperty("jvmRoute"); - } - Tomcat tomcat = ((TomcatWebServer) this.webServer).getTomcat(); - Context context = (Context) tomcat.getHost().findChildren()[0]; - SessionIdGenerator sessionIdGenerator = context.getManager().getSessionIdGenerator(); - assertThat(sessionIdGenerator).isInstanceOf(LazySessionIdGenerator.class); - assertThat(sessionIdGenerator.getJvmRoute()).isEqualTo("test"); - } - @Test void tldSkipPatternsShouldBeAppliedToContextJarScanner() { TomcatServletWebServerFactory factory = getFactory(); @@ -497,7 +486,7 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory @Test void customTomcatHttpOnlyCookie() { TomcatServletWebServerFactory factory = getFactory(); - factory.getSession().getCookie().setHttpOnly(false); + factory.getSettings().getSession().getCookie().setHttpOnly(false); this.webServer = factory.getWebServer(); this.webServer.start(); Tomcat tomcat = ((TomcatWebServer) this.webServer).getTomcat(); @@ -609,7 +598,7 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory @Test void whenServerIsShuttingDownGracefullyThenNewConnectionsCannotBeMade() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + TomcatServletWebServerFactory factory = getFactory(); factory.setShutdown(Shutdown.GRACEFUL); BlockingServlet blockingServlet = new BlockingServlet(); this.webServer = factory.getWebServer((context) -> { @@ -634,7 +623,7 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory @Test void whenServerIsShuttingDownARequestOnAnIdleConnectionResultsInConnectionReset() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + TomcatServletWebServerFactory factory = getFactory(); factory.setShutdown(Shutdown.GRACEFUL); BlockingServlet blockingServlet = new BlockingServlet(); this.webServer = factory.getWebServer((context) -> { @@ -760,7 +749,7 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory @Override protected String startedLogMessage() { - return ((TomcatWebServer) this.webServer).getStartedLogMessage(); + return TomcatAccess.getStartedLogMessage((TomcatWebServer) this.webServer); } private static final class RememberingHostnameVerifier implements HostnameVerifier { diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/FileSessionPersistenceTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/undertow/FileSessionPersistenceTests.java similarity index 96% rename from spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/FileSessionPersistenceTests.java rename to spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/undertow/FileSessionPersistenceTests.java index 5c4eac26d1..568c84bc95 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/FileSessionPersistenceTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/undertow/FileSessionPersistenceTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.undertow; +package org.springframework.boot.web.server.servlet.undertow; import java.io.File; import java.util.Date; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/JarResourceManagerTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/undertow/JarResourceManagerTests.java similarity index 96% rename from spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/JarResourceManagerTests.java rename to spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/undertow/JarResourceManagerTests.java index 131b254a6d..321efe2440 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/JarResourceManagerTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/undertow/JarResourceManagerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.undertow; +package org.springframework.boot.web.server.servlet.undertow; import java.io.File; import java.io.FileOutputStream; 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/server/servlet/undertow/UndertowServletWebServerFactoryTests.java similarity index 95% rename from spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/UndertowServletWebServerFactoryTests.java rename to spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/servlet/undertow/UndertowServletWebServerFactoryTests.java index 28c58c3c07..b74127f693 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/server/servlet/undertow/UndertowServletWebServerFactoryTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.undertow; +package org.springframework.boot.web.server.servlet.undertow; import java.io.File; import java.io.IOException; @@ -54,9 +54,10 @@ 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.servlet.AbstractServletWebServerFactoryTests; +import org.springframework.boot.web.server.servlet.ConfigurableServletWebServerFactory; +import org.springframework.boot.web.server.undertow.UndertowBuilderCustomizer; import org.springframework.boot.web.servlet.ServletRegistrationBean; -import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactory; -import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactoryTests; import org.springframework.http.HttpStatus; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.test.util.ReflectionTestUtils; @@ -91,7 +92,7 @@ class UndertowServletWebServerFactoryTests extends AbstractServletWebServerFacto @Test void errorPage404() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/hello")); this.webServer = factory.getWebServer(new ServletRegistrationBean<>(new ExampleServlet(), "/hello")); this.webServer.start(); @@ -196,7 +197,7 @@ class UndertowServletWebServerFactoryTests extends AbstractServletWebServerFacto @Test void whenServerIsShuttingDownGracefullyThenRequestsAreRejectedWithServiceUnavailable() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.setShutdown(Shutdown.GRACEFUL); BlockingServlet blockingServlet = new BlockingServlet(); this.webServer = factory.getWebServer((context) -> { @@ -221,7 +222,7 @@ class UndertowServletWebServerFactoryTests extends AbstractServletWebServerFacto @Test void whenServerIsShuttingDownARequestOnAnIdleConnectionAreRejectedWithServiceUnavailable() throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.setShutdown(Shutdown.GRACEFUL); BlockingServlet blockingServlet = new BlockingServlet(); this.webServer = factory.getWebServer((context) -> { @@ -285,7 +286,7 @@ class UndertowServletWebServerFactoryTests extends AbstractServletWebServerFacto } @Override - protected void addConnector(int port, AbstractServletWebServerFactory factory) { + protected void addConnector(int port, ConfigurableServletWebServerFactory factory) { ((UndertowServletWebServerFactory) factory) .addBuilderCustomizers((builder) -> builder.addHttpListener(port, "0.0.0.0")); } @@ -382,11 +383,11 @@ class UndertowServletWebServerFactoryTests extends AbstractServletWebServerFacto @Override protected String startedLogMessage() { - return ((UndertowServletWebServer) this.webServer).getStartLogMessage(); + return ((UndertowServletWebServer) this.webServer).getStartedLogMessage(); } private void testRestrictedSSLProtocolsAndCipherSuites(String[] protocols, String[] ciphers) throws Exception { - AbstractServletWebServerFactory factory = getFactory(); + ConfigurableServletWebServerFactory factory = getFactory(); factory.setSsl(getSsl(null, "password", "classpath:restricted.jks", null, protocols, ciphers)); this.webServer = factory.getWebServer(new ServletRegistrationBean<>(new ExampleServlet(true, false), "/hello")); this.webServer.start(); diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/CompressionConnectorCustomizerTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/tomcat/CompressionConnectorCustomizerTests.java similarity index 96% rename from spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/CompressionConnectorCustomizerTests.java rename to spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/tomcat/CompressionConnectorCustomizerTests.java index c826909806..200c554f61 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/CompressionConnectorCustomizerTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/tomcat/CompressionConnectorCustomizerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.tomcat; +package org.springframework.boot.web.server.tomcat; import org.apache.catalina.connector.Connector; import org.apache.coyote.http11.AbstractHttp11Protocol; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/SslConnectorCustomizerTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/tomcat/SslConnectorCustomizerTests.java similarity index 99% rename from spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/SslConnectorCustomizerTests.java rename to spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/tomcat/SslConnectorCustomizerTests.java index f8ff57396d..30732875a3 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/SslConnectorCustomizerTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/tomcat/SslConnectorCustomizerTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.tomcat; +package org.springframework.boot.web.server.tomcat; import java.util.Collections; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/tomcat/TomcatAccess.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/tomcat/TomcatAccess.java new file mode 100644 index 0000000000..8dba14ea7b --- /dev/null +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/tomcat/TomcatAccess.java @@ -0,0 +1,43 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.web.server.tomcat; + +import java.util.Map; + +import org.apache.catalina.Service; +import org.apache.catalina.connector.Connector; + +/** + * Helper class to provide public access to package-private methods for testing purposes. + * + * @author Andy Wilkinson + */ +public final class TomcatAccess { + + private TomcatAccess() { + + } + + public static Map getServiceConnectors(TomcatWebServer tomcatWebServer) { + return tomcatWebServer.getServiceConnectors(); + } + + public static String getStartedLogMessage(TomcatWebServer tomcatWebServer) { + return tomcatWebServer.getStartedLogMessage(); + } + +} diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedWebappClassLoaderTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/tomcat/TomcatEmbeddedWebappClassLoaderTests.java similarity index 97% rename from spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedWebappClassLoaderTests.java rename to spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/tomcat/TomcatEmbeddedWebappClassLoaderTests.java index 7dd30e2735..8186e750d4 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedWebappClassLoaderTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/tomcat/TomcatEmbeddedWebappClassLoaderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.tomcat; +package org.springframework.boot.web.server.tomcat; import java.io.File; import java.io.FileOutputStream; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/undertow/UndertowAccess.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/undertow/UndertowAccess.java new file mode 100644 index 0000000000..c69ba937bb --- /dev/null +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/undertow/UndertowAccess.java @@ -0,0 +1,34 @@ +/* + * Copyright 2012-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.web.server.undertow; + +/** + * Helper class to provide public access to package-private methods for testing purposes. + * + * @author Andy Wilkinson + */ +public final class UndertowAccess { + + private UndertowAccess() { + + } + + public static String getStartedLogMessage(UndertowWebServer undertowWebServer) { + return undertowWebServer.getStartedLogMessage(); + } + +} diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/UndertowWebServerRuntimeHintsTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/undertow/UndertowWebServerRuntimeHintsTests.java similarity index 93% rename from spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/UndertowWebServerRuntimeHintsTests.java rename to spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/undertow/UndertowWebServerRuntimeHintsTests.java index fdc73e1459..ee62189215 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/UndertowWebServerRuntimeHintsTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/undertow/UndertowWebServerRuntimeHintsTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.embedded.undertow; +package org.springframework.boot.web.server.undertow; import java.util.function.Predicate; @@ -23,7 +23,7 @@ import org.junit.jupiter.api.Test; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; -import org.springframework.boot.web.embedded.undertow.UndertowWebServer.UndertowWebServerRuntimeHints; +import org.springframework.boot.web.server.undertow.UndertowWebServer.UndertowWebServerRuntimeHints; import org.springframework.util.ReflectionUtils; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/FilterRegistrationIntegrationTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/FilterRegistrationIntegrationTests.java index e6ae1b1b80..9af97a481b 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/FilterRegistrationIntegrationTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/FilterRegistrationIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ import jakarta.servlet.Filter; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.boot.web.servlet.mock.MockFilter; import org.springframework.context.annotation.Bean; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/MockWebEnvironmentServletComponentScanIntegrationTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/MockWebEnvironmentServletComponentScanIntegrationTests.java index 1fe7a87f79..aaf0889ea6 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/MockWebEnvironmentServletComponentScanIntegrationTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/MockWebEnvironmentServletComponentScanIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,6 +33,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.springframework.boot.testsupport.classpath.ForkedClassPath; +import org.springframework.boot.web.server.servlet.WebListenerRegistry; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebApplicationContext; import org.springframework.boot.web.servlet.testcomponents.filter.TestFilter; import org.springframework.boot.web.servlet.testcomponents.listener.TestListener; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletComponentScanIntegrationTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletComponentScanIntegrationTests.java index b955eed395..72bdc2de83 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletComponentScanIntegrationTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletComponentScanIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,12 +39,12 @@ import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.testsupport.classpath.ForkedClassPath; import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories; import org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer; -import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; -import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory; +import org.springframework.boot.web.server.servlet.ConfigurableServletWebServerFactory; +import org.springframework.boot.web.server.servlet.ServletWebServerFactory; +import org.springframework.boot.web.server.servlet.jetty.JettyServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.servlet.undertow.UndertowServletWebServerFactory; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; -import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; -import org.springframework.boot.web.servlet.server.ServletWebServerFactory; import org.springframework.boot.web.servlet.testcomponents.filter.TestFilter; import org.springframework.boot.web.servlet.testcomponents.listener.TestListener; import org.springframework.boot.web.servlet.testcomponents.servlet.TestMultipartServlet; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java index c1cafa0c47..4b276204ab 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java @@ -36,6 +36,7 @@ import jakarta.servlet.http.HttpSessionIdListener; import org.assertj.core.api.ThrowingConsumer; import org.junit.jupiter.api.Test; +import org.springframework.boot.web.server.servlet.ServletContextInitializer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/context/AnnotationConfigServletWebServerApplicationContextTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/context/AnnotationConfigServletWebServerApplicationContextTests.java index 362cce3cea..3dd50d2fec 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/context/AnnotationConfigServletWebServerApplicationContextTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/context/AnnotationConfigServletWebServerApplicationContextTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,10 +25,10 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.web.server.servlet.MockServletWebServerFactory; +import org.springframework.boot.web.server.servlet.ServletWebServerFactory; import org.springframework.boot.web.servlet.context.config.ExampleServletWebServerApplicationConfiguration; import org.springframework.boot.web.servlet.mock.MockServlet; -import org.springframework.boot.web.servlet.server.MockServletWebServerFactory; -import org.springframework.boot.web.servlet.server.ServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/context/ServletWebServerApplicationContextTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/context/ServletWebServerApplicationContextTests.java index 9b78cc1fe6..a784bcd79c 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/context/ServletWebServerApplicationContextTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/context/ServletWebServerApplicationContextTests.java @@ -52,11 +52,11 @@ import org.springframework.boot.testsupport.system.CapturedOutput; import org.springframework.boot.testsupport.system.OutputCaptureExtension; import org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer; import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.servlet.MockServletWebServerFactory; +import org.springframework.boot.web.server.servlet.ServletContextInitializer; import org.springframework.boot.web.servlet.DelegatingFilterProxyRegistrationBean; import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.boot.web.servlet.ServletRegistrationBean; -import org.springframework.boot.web.servlet.server.MockServletWebServerFactory; import org.springframework.context.ApplicationContextException; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/context/ServletWebServerMvcIntegrationTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/context/ServletWebServerMvcIntegrationTests.java index ac717b24fa..82dce656fa 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/context/ServletWebServerMvcIntegrationTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/context/ServletWebServerMvcIntegrationTests.java @@ -23,12 +23,12 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.testsupport.classpath.resources.WithResource; import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories; -import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; -import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory; import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.servlet.ServletWebServerFactory; +import org.springframework.boot.web.server.servlet.jetty.JettyServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.servlet.undertow.UndertowServletWebServerFactory; import org.springframework.boot.web.servlet.ServletRegistrationBean; -import org.springframework.boot.web.servlet.server.ServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/context/XmlServletWebServerApplicationContextTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/context/XmlServletWebServerApplicationContextTests.java index e8496ade45..c5fb187266 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/context/XmlServletWebServerApplicationContextTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/context/XmlServletWebServerApplicationContextTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,7 @@ package org.springframework.boot.web.servlet.context; import jakarta.servlet.Servlet; import org.junit.jupiter.api.Test; -import org.springframework.boot.web.servlet.server.MockServletWebServerFactory; +import org.springframework.boot.web.server.servlet.MockServletWebServerFactory; import org.springframework.core.io.ClassPathResource; import static org.mockito.BDDMockito.then; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/context/config/ExampleServletWebServerApplicationConfiguration.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/context/config/ExampleServletWebServerApplicationConfiguration.java index 0e1cd911a8..e41963e782 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/context/config/ExampleServletWebServerApplicationConfiguration.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/context/config/ExampleServletWebServerApplicationConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,8 +18,8 @@ package org.springframework.boot.web.servlet.context.config; import jakarta.servlet.Servlet; +import org.springframework.boot.web.server.servlet.MockServletWebServerFactory; import org.springframework.boot.web.servlet.mock.MockServlet; -import org.springframework.boot.web.servlet.server.MockServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/support/ErrorPageFilterIntegrationTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/support/ErrorPageFilterIntegrationTests.java index 565bcd2307..671e9ef964 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/support/ErrorPageFilterIntegrationTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/support/ErrorPageFilterIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,9 +27,9 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.servlet.ServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; -import org.springframework.boot.web.servlet.server.ServletWebServerFactory; import org.springframework.boot.web.servlet.support.ErrorPageFilterIntegrationTests.EmbeddedWebContextLoader; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/support/SpringBootServletInitializerTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/support/SpringBootServletInitializerTests.java index f770433034..1002979581 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/support/SpringBootServletInitializerTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/support/SpringBootServletInitializerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,10 +40,10 @@ import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEven import org.springframework.boot.context.logging.LoggingApplicationListener; import org.springframework.boot.testsupport.system.CapturedOutput; import org.springframework.boot.testsupport.system.OutputCaptureExtension; -import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory; import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.servlet.ServletWebServerFactory; +import org.springframework.boot.web.server.servlet.undertow.UndertowServletWebServerFactory; import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.boot.web.servlet.server.ServletWebServerFactory; import org.springframework.context.ApplicationListener; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; diff --git a/spring-boot-project/spring-boot/src/test/kotlin/org/springframework/boot/SpringApplicationExtensionsTests.kt b/spring-boot-project/spring-boot/src/test/kotlin/org/springframework/boot/SpringApplicationExtensionsTests.kt index 45701458c0..91515ed720 100644 --- a/spring-boot-project/spring-boot/src/test/kotlin/org/springframework/boot/SpringApplicationExtensionsTests.kt +++ b/spring-boot-project/spring-boot/src/test/kotlin/org/springframework/boot/SpringApplicationExtensionsTests.kt @@ -22,7 +22,7 @@ import org.junit.jupiter.api.Test import org.springframework.beans.factory.getBean import org.springframework.boot.kotlinsample.TestKotlinApplication import org.springframework.boot.web.servlet.mock.MockFilter -import org.springframework.boot.web.servlet.server.MockServletWebServerFactory +import org.springframework.boot.web.server.servlet.MockServletWebServerFactory import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.core.env.StandardEnvironment diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/embedded/jetty/test.jks b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/jetty/test.jks similarity index 100% rename from spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/embedded/jetty/test.jks rename to spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/jetty/test.jks diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/embedded/netty/1.crt b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/reactive/netty/1.crt similarity index 100% rename from spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/embedded/netty/1.crt rename to spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/reactive/netty/1.crt diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/embedded/netty/1.key b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/reactive/netty/1.key similarity index 100% rename from spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/embedded/netty/1.key rename to spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/reactive/netty/1.key diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/embedded/netty/2.crt b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/reactive/netty/2.crt similarity index 100% rename from spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/embedded/netty/2.crt rename to spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/reactive/netty/2.crt diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/embedded/netty/2.key b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/reactive/netty/2.key similarity index 100% rename from spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/embedded/netty/2.key rename to spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/reactive/netty/2.key diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/embedded/netty/test.jks b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/reactive/netty/test.jks similarity index 100% rename from spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/embedded/netty/test.jks rename to spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/reactive/netty/test.jks diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/reactive/server/test-cert.pem b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/reactive/test-cert.pem similarity index 100% rename from spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/reactive/server/test-cert.pem rename to spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/reactive/test-cert.pem diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/reactive/server/test-key.pem b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/reactive/test-key.pem similarity index 100% rename from spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/reactive/server/test-key.pem rename to spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/reactive/test-key.pem diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/embedded/tomcat/test.jks b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/reactive/test.jks similarity index 100% rename from spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/embedded/tomcat/test.jks rename to spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/reactive/test.jks diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/reactive/server/test.p12 b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/reactive/test.p12 similarity index 100% rename from spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/reactive/server/test.p12 rename to spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/reactive/test.p12 diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/embedded/undertow/test.jks b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/servlet/jetty/test.jks similarity index 100% rename from spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/embedded/undertow/test.jks rename to spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/servlet/jetty/test.jks diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/servlet/server/test-cert.pem b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/servlet/test-cert.pem similarity index 100% rename from spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/servlet/server/test-cert.pem rename to spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/servlet/test-cert.pem diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/servlet/server/test-key.pem b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/servlet/test-key.pem similarity index 100% rename from spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/servlet/server/test-key.pem rename to spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/servlet/test-key.pem diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/reactive/server/test.jks b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/servlet/test.jks similarity index 100% rename from spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/reactive/server/test.jks rename to spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/servlet/test.jks diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/servlet/server/test.p12 b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/servlet/test.p12 similarity index 100% rename from spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/servlet/server/test.p12 rename to spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/servlet/test.p12 diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/embedded/tomcat/1.crt b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/servlet/tomcat/1.crt similarity index 100% rename from spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/embedded/tomcat/1.crt rename to spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/servlet/tomcat/1.crt diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/embedded/tomcat/1.key b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/servlet/tomcat/1.key similarity index 100% rename from spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/embedded/tomcat/1.key rename to spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/servlet/tomcat/1.key diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/embedded/tomcat/2.crt b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/servlet/tomcat/2.crt similarity index 100% rename from spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/embedded/tomcat/2.crt rename to spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/servlet/tomcat/2.crt diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/embedded/tomcat/2.key b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/servlet/tomcat/2.key similarity index 100% rename from spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/embedded/tomcat/2.key rename to spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/servlet/tomcat/2.key diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/servlet/server/test.jks b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/servlet/tomcat/test.jks similarity index 100% rename from spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/servlet/server/test.jks rename to spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/servlet/tomcat/test.jks diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/embedded/undertow/restricted.jks b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/servlet/undertow/restricted.jks similarity index 100% rename from spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/embedded/undertow/restricted.jks rename to spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/servlet/undertow/restricted.jks diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/servlet/undertow/test.jks b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/servlet/undertow/test.jks new file mode 100644 index 0000000000..74279d80fb Binary files /dev/null and b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/servlet/undertow/test.jks differ diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/tomcat/test.jks b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/tomcat/test.jks new file mode 100644 index 0000000000..74279d80fb Binary files /dev/null and b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/tomcat/test.jks differ diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/undertow/test.jks b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/undertow/test.jks new file mode 100644 index 0000000000..74279d80fb Binary files /dev/null and b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/server/undertow/test.jks differ diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/servlet/context/exampleEmbeddedWebApplicationConfiguration.xml b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/servlet/context/exampleEmbeddedWebApplicationConfiguration.xml index e220798078..76d72bef23 100644 --- a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/servlet/context/exampleEmbeddedWebApplicationConfiguration.xml +++ b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/servlet/context/exampleEmbeddedWebApplicationConfiguration.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> + class="org.springframework.boot.web.server.servlet.MockServletWebServerFactory" /> diff --git a/spring-boot-project/spring-boot/src/testFixtures/java/org/springframework/boot/web/reactive/server/MockReactiveWebServer.java b/spring-boot-project/spring-boot/src/testFixtures/java/org/springframework/boot/web/server/reactive/MockReactiveWebServer.java similarity index 96% rename from spring-boot-project/spring-boot/src/testFixtures/java/org/springframework/boot/web/reactive/server/MockReactiveWebServer.java rename to spring-boot-project/spring-boot/src/testFixtures/java/org/springframework/boot/web/server/reactive/MockReactiveWebServer.java index 560a22f501..71ef461fab 100644 --- a/spring-boot-project/spring-boot/src/testFixtures/java/org/springframework/boot/web/reactive/server/MockReactiveWebServer.java +++ b/spring-boot-project/spring-boot/src/testFixtures/java/org/springframework/boot/web/server/reactive/MockReactiveWebServer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.reactive.server; +package org.springframework.boot.web.server.reactive; import java.util.Map; diff --git a/spring-boot-project/spring-boot/src/testFixtures/java/org/springframework/boot/web/reactive/server/MockReactiveWebServerFactory.java b/spring-boot-project/spring-boot/src/testFixtures/java/org/springframework/boot/web/server/reactive/MockReactiveWebServerFactory.java similarity index 95% rename from spring-boot-project/spring-boot/src/testFixtures/java/org/springframework/boot/web/reactive/server/MockReactiveWebServerFactory.java rename to spring-boot-project/spring-boot/src/testFixtures/java/org/springframework/boot/web/server/reactive/MockReactiveWebServerFactory.java index 1566c3383e..3237cd0d25 100644 --- a/spring-boot-project/spring-boot/src/testFixtures/java/org/springframework/boot/web/reactive/server/MockReactiveWebServerFactory.java +++ b/spring-boot-project/spring-boot/src/testFixtures/java/org/springframework/boot/web/server/reactive/MockReactiveWebServerFactory.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.reactive.server; +package org.springframework.boot.web.server.reactive; import org.springframework.boot.web.server.WebServer; import org.springframework.http.server.reactive.HttpHandler; diff --git a/spring-boot-project/spring-boot/src/testFixtures/java/org/springframework/boot/web/servlet/server/MockServletWebServer.java b/spring-boot-project/spring-boot/src/testFixtures/java/org/springframework/boot/web/server/servlet/MockServletWebServer.java similarity index 96% rename from spring-boot-project/spring-boot/src/testFixtures/java/org/springframework/boot/web/servlet/server/MockServletWebServer.java rename to spring-boot-project/spring-boot/src/testFixtures/java/org/springframework/boot/web/server/servlet/MockServletWebServer.java index 6338acd3a1..e4c318c0ca 100644 --- a/spring-boot-project/spring-boot/src/testFixtures/java/org/springframework/boot/web/servlet/server/MockServletWebServer.java +++ b/spring-boot-project/spring-boot/src/testFixtures/java/org/springframework/boot/web/server/servlet/MockServletWebServer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.web.servlet.server; +package org.springframework.boot.web.server.servlet; import java.util.ArrayList; import java.util.Arrays; @@ -22,6 +22,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.StreamSupport; import jakarta.servlet.Filter; import jakarta.servlet.FilterRegistration; @@ -33,7 +34,6 @@ import jakarta.servlet.SessionCookieConfig; import org.springframework.boot.web.server.WebServer; import org.springframework.boot.web.server.WebServerException; -import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.mock.web.MockSessionCookieConfig; import static org.mockito.ArgumentMatchers.any; @@ -60,8 +60,8 @@ public class MockServletWebServer implements WebServer { private final int port; - MockServletWebServer(ServletContextInitializer[] initializers, int port) { - this(Arrays.stream(initializers) + MockServletWebServer(ServletContextInitializers initializers, int port) { + this(StreamSupport.stream(initializers.spliterator(), false) .map((initializer) -> (Initializer) initializer::onStartup) .toArray(Initializer[]::new), port); } diff --git a/spring-boot-project/spring-boot/src/testFixtures/java/org/springframework/boot/web/servlet/server/MockServletWebServerFactory.java b/spring-boot-project/spring-boot/src/testFixtures/java/org/springframework/boot/web/server/servlet/MockServletWebServerFactory.java similarity index 69% rename from spring-boot-project/spring-boot/src/testFixtures/java/org/springframework/boot/web/servlet/server/MockServletWebServerFactory.java rename to spring-boot-project/spring-boot/src/testFixtures/java/org/springframework/boot/web/server/servlet/MockServletWebServerFactory.java index 59151d615e..1772d8f392 100644 --- a/spring-boot-project/spring-boot/src/testFixtures/java/org/springframework/boot/web/servlet/server/MockServletWebServerFactory.java +++ b/spring-boot-project/spring-boot/src/testFixtures/java/org/springframework/boot/web/server/servlet/MockServletWebServerFactory.java @@ -14,14 +14,14 @@ * limitations under the License. */ -package org.springframework.boot.web.servlet.server; +package org.springframework.boot.web.server.servlet; import jakarta.servlet.ServletContext; +import org.springframework.boot.web.server.AbstractConfigurableWebServerFactory; import org.springframework.boot.web.server.WebServer; -import org.springframework.boot.web.servlet.ServletContextInitializer; -import org.springframework.boot.web.servlet.server.MockServletWebServer.RegisteredFilter; -import org.springframework.boot.web.servlet.server.MockServletWebServer.RegisteredServlet; +import org.springframework.boot.web.server.servlet.MockServletWebServer.RegisteredFilter; +import org.springframework.boot.web.server.servlet.MockServletWebServer.RegisteredServlet; import static org.mockito.Mockito.spy; @@ -31,13 +31,17 @@ import static org.mockito.Mockito.spy; * @author Phillip Webb * @author Andy Wilkinson */ -public class MockServletWebServerFactory extends AbstractServletWebServerFactory { +public class MockServletWebServerFactory extends AbstractConfigurableWebServerFactory + implements ConfigurableServletWebServerFactory { + + private final ServletWebServerSettings settings = new ServletWebServerSettings(); private MockServletWebServer webServer; @Override public WebServer getWebServer(ServletContextInitializer... initializers) { - this.webServer = spy(new MockServletWebServer(mergeInitializers(initializers), getPort())); + this.webServer = spy( + new MockServletWebServer(ServletContextInitializers.from(this.settings, initializers), getPort())); return this.webServer; } @@ -57,4 +61,9 @@ public class MockServletWebServerFactory extends AbstractServletWebServerFactory return (getWebServer() != null) ? getWebServer().getRegisteredFilters(index) : null; } + @Override + public ServletWebServerSettings getSettings() { + return this.settings; + } + } diff --git a/spring-boot-tests/spring-boot-integration-tests/spring-boot-server-tests/spring-boot-server-tests-app/src/main/java/com/example/JettyServerCustomizerConfig.java b/spring-boot-tests/spring-boot-integration-tests/spring-boot-server-tests/spring-boot-server-tests-app/src/main/java/com/example/JettyServerCustomizerConfig.java index 7e18b58220..a642b7f789 100644 --- a/spring-boot-tests/spring-boot-integration-tests/spring-boot-server-tests/spring-boot-server-tests-app/src/main/java/com/example/JettyServerCustomizerConfig.java +++ b/spring-boot-tests/spring-boot-integration-tests/spring-boot-server-tests/spring-boot-server-tests-app/src/main/java/com/example/JettyServerCustomizerConfig.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,7 +23,7 @@ import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.handler.ContextHandler; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer; +import org.springframework.boot.web.server.jetty.JettyServerCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jetty-ssl/src/test/java/smoketest/jetty/ssl/SampleJettySslApplicationTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jetty-ssl/src/test/java/smoketest/jetty/ssl/SampleJettySslApplicationTests.java index 983c6cd24c..f5a581238f 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jetty-ssl/src/test/java/smoketest/jetty/ssl/SampleJettySslApplicationTests.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jetty-ssl/src/test/java/smoketest/jetty/ssl/SampleJettySslApplicationTests.java @@ -33,7 +33,7 @@ import static org.assertj.core.api.Assertions.assertThat; * * @author Dave Syer */ -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = "debug=true") class SampleJettySslApplicationTests { @Autowired diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-tomcat-multi-connectors/src/main/java/smoketest/tomcat/multiconnector/SampleTomcatTwoConnectorsApplication.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-tomcat-multi-connectors/src/main/java/smoketest/tomcat/multiconnector/SampleTomcatTwoConnectorsApplication.java index e8a77101ef..38cf5eaa9d 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-tomcat-multi-connectors/src/main/java/smoketest/tomcat/multiconnector/SampleTomcatTwoConnectorsApplication.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-tomcat-multi-connectors/src/main/java/smoketest/tomcat/multiconnector/SampleTomcatTwoConnectorsApplication.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,8 +20,8 @@ import org.apache.catalina.connector.Connector; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; -import org.springframework.boot.web.servlet.server.ServletWebServerFactory; +import org.springframework.boot.web.server.servlet.ServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.context.annotation.Bean; /** @@ -36,7 +36,7 @@ public class SampleTomcatTwoConnectorsApplication { @Bean public ServletWebServerFactory servletContainer() { TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory(); - tomcat.addAdditionalTomcatConnectors(createStandardConnector()); + tomcat.addAdditionalConnectors(createStandardConnector()); return tomcat; } diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-tomcat-multi-connectors/src/test/java/smoketest/tomcat/multiconnector/SampleTomcatTwoConnectorsApplicationTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-tomcat-multi-connectors/src/test/java/smoketest/tomcat/multiconnector/SampleTomcatTwoConnectorsApplicationTests.java index 9e429a9321..19987a009c 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-tomcat-multi-connectors/src/test/java/smoketest/tomcat/multiconnector/SampleTomcatTwoConnectorsApplicationTests.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-tomcat-multi-connectors/src/test/java/smoketest/tomcat/multiconnector/SampleTomcatTwoConnectorsApplicationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,8 +28,8 @@ import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.boot.web.context.WebServerInitializedEvent; -import org.springframework.boot.web.embedded.tomcat.TomcatWebServer; import org.springframework.boot.web.server.AbstractConfigurableWebServerFactory; +import org.springframework.boot.web.server.tomcat.TomcatWebServer; import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.Import; import org.springframework.http.HttpStatus; diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-tomcat/src/test/java/smoketest/tomcat/NonAutoConfigurationSampleTomcatApplicationTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-tomcat/src/test/java/smoketest/tomcat/NonAutoConfigurationSampleTomcatApplicationTests.java index 921d23ac54..7658db73d7 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-tomcat/src/test/java/smoketest/tomcat/NonAutoConfigurationSampleTomcatApplicationTests.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-tomcat/src/test/java/smoketest/tomcat/NonAutoConfigurationSampleTomcatApplicationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,8 +24,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; @@ -57,7 +57,7 @@ class NonAutoConfigurationSampleTomcatApplicationTests { } @Configuration(proxyBeanMethods = false) - @Import({ ServletWebServerFactoryAutoConfiguration.class, DispatcherServletAutoConfiguration.class, + @Import({ TomcatServletWebServerAutoConfiguration.class, DispatcherServletAutoConfiguration.class, WebMvcAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class }) @ComponentScan(basePackageClasses = { SampleController.class, HelloWorldService.class }) diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-tomcat/src/test/java/smoketest/tomcat/SampleTomcatApplicationTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-tomcat/src/test/java/smoketest/tomcat/SampleTomcatApplicationTests.java index c3dae372c2..92534b0e37 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-tomcat/src/test/java/smoketest/tomcat/SampleTomcatApplicationTests.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-tomcat/src/test/java/smoketest/tomcat/SampleTomcatApplicationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,7 +33,7 @@ import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.system.CapturedOutput; import org.springframework.boot.test.system.OutputCaptureExtension; import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.web.embedded.tomcat.TomcatWebServer; +import org.springframework.boot.web.server.tomcat.TomcatWebServer; import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext; import org.springframework.context.ApplicationContext; import org.springframework.http.HttpEntity; diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-tomcat11/src/test/java/smoketest/tomcat/NonAutoConfigurationSampleTomcatApplicationTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-tomcat11/src/test/java/smoketest/tomcat/NonAutoConfigurationSampleTomcatApplicationTests.java index 50d5e693c7..4a94c8068c 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-tomcat11/src/test/java/smoketest/tomcat/NonAutoConfigurationSampleTomcatApplicationTests.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-tomcat11/src/test/java/smoketest/tomcat/NonAutoConfigurationSampleTomcatApplicationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,8 +24,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration; +import org.springframework.boot.autoconfigure.web.server.servlet.tomcat.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; @@ -57,7 +57,7 @@ class NonAutoConfigurationSampleTomcatApplicationTests { } @Configuration(proxyBeanMethods = false) - @Import({ ServletWebServerFactoryAutoConfiguration.class, DispatcherServletAutoConfiguration.class, + @Import({ TomcatServletWebServerAutoConfiguration.class, DispatcherServletAutoConfiguration.class, WebMvcAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class }) @ComponentScan(basePackageClasses = { SampleController.class, HelloWorldService.class }) diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-tomcat11/src/test/java/smoketest/tomcat/SampleTomcat11ApplicationTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-tomcat11/src/test/java/smoketest/tomcat/SampleTomcat11ApplicationTests.java index f9d660878c..8dbbbebb42 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-tomcat11/src/test/java/smoketest/tomcat/SampleTomcat11ApplicationTests.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-tomcat11/src/test/java/smoketest/tomcat/SampleTomcat11ApplicationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,7 +33,7 @@ import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.system.CapturedOutput; import org.springframework.boot.test.system.OutputCaptureExtension; import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.web.embedded.tomcat.TomcatWebServer; +import org.springframework.boot.web.server.tomcat.TomcatWebServer; import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext; import org.springframework.context.ApplicationContext; import org.springframework.http.HttpEntity; diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-websocket-jetty/src/test/java/smoketest/websocket/jetty/echo/CustomContainerWebSocketsApplicationTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-websocket-jetty/src/test/java/smoketest/websocket/jetty/echo/CustomContainerWebSocketsApplicationTests.java index 0f4670c14d..2b8ff1b0a3 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-websocket-jetty/src/test/java/smoketest/websocket/jetty/echo/CustomContainerWebSocketsApplicationTests.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-websocket-jetty/src/test/java/smoketest/websocket/jetty/echo/CustomContainerWebSocketsApplicationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,8 +36,8 @@ import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory; -import org.springframework.boot.web.servlet.server.ServletWebServerFactory; +import org.springframework.boot.web.server.servlet.ServletWebServerFactory; +import org.springframework.boot.web.server.servlet.jetty.JettyServletWebServerFactory; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-websocket-tomcat/src/test/java/smoketest/websocket/tomcat/echo/CustomContainerWebSocketsApplicationTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-websocket-tomcat/src/test/java/smoketest/websocket/tomcat/echo/CustomContainerWebSocketsApplicationTests.java index ccc90761d2..6d41c6d6b2 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-websocket-tomcat/src/test/java/smoketest/websocket/tomcat/echo/CustomContainerWebSocketsApplicationTests.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-websocket-tomcat/src/test/java/smoketest/websocket/tomcat/echo/CustomContainerWebSocketsApplicationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,8 +36,8 @@ import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; -import org.springframework.boot.web.servlet.server.ServletWebServerFactory; +import org.springframework.boot.web.server.servlet.ServletWebServerFactory; +import org.springframework.boot.web.server.servlet.tomcat.TomcatServletWebServerFactory; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-websocket-undertow/src/test/java/smoketest/websocket/undertow/echo/CustomContainerWebSocketsApplicationTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-websocket-undertow/src/test/java/smoketest/websocket/undertow/echo/CustomContainerWebSocketsApplicationTests.java index 7869d4cfea..af24f1b367 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-websocket-undertow/src/test/java/smoketest/websocket/undertow/echo/CustomContainerWebSocketsApplicationTests.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-websocket-undertow/src/test/java/smoketest/websocket/undertow/echo/CustomContainerWebSocketsApplicationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,8 +36,8 @@ import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory; -import org.springframework.boot.web.servlet.server.ServletWebServerFactory; +import org.springframework.boot.web.server.servlet.ServletWebServerFactory; +import org.springframework.boot.web.server.servlet.undertow.UndertowServletWebServerFactory; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/src/checkstyle/import-control.xml b/src/checkstyle/import-control.xml index e45b3b7050..24dda45472 100644 --- a/src/checkstyle/import-control.xml +++ b/src/checkstyle/import-control.xml @@ -17,12 +17,26 @@ - - + + + + + + + + + + + + + + + + + - @@ -31,7 +45,6 @@ - @@ -103,11 +116,42 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -116,6 +160,7 @@ + @@ -126,11 +171,6 @@ - - - - - @@ -166,14 +206,5 @@ - - - - - - - - -