Upgrade to Servlet 6.0 and related EE 10 specs

Co-authored-by: Phillip Webb <pwebb@vmware.com>

Closes gh-33036
Closes gh-33037
Closes gh-33038
Closes gh-33039
Closes gh-33040
Closes gh-33041
Closes gh-33042
Closes gh-33043
This commit is contained in:
Andy Wilkinson 2022-11-05 17:57:18 -07:00
parent 1525ed9170
commit b67c427259
36 changed files with 188 additions and 62 deletions

View File

@ -5,7 +5,7 @@ org.gradle.parallel=true
org.gradle.jvmargs=-Xmx2g -Dfile.encoding=UTF-8
kotlinVersion=1.7.20
tomcatVersion=10.0.27
tomcatVersion=10.1.1
nativeBuildToolsVersion=0.9.17
kotlin.stdlib.default.dependency=false

View File

@ -153,9 +153,7 @@ dependencies {
testImplementation("com.squareup.okhttp3:mockwebserver")
testImplementation("com.jayway.jsonpath:json-path")
testImplementation("io.undertow:undertow-core")
testImplementation("io.undertow:undertow-servlet-jakarta") {
exclude group: "org.jboss.spec.javax.annotation", module: "jboss-annotations-api_1.3_spec"
}
testImplementation("io.undertow:undertow-servlet")
testImplementation("jakarta.xml.bind:jakarta.xml.bind-api")
testImplementation("org.apache.activemq:artemis-jakarta-client") {
exclude group: "commons-logging", module: "commons-logging"

View File

@ -31,6 +31,7 @@ import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactor
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.web.servlet.Servlet5ClassPathOverrides;
import org.springframework.boot.web.embedded.jetty.JettyReactiveWebServerFactory;
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext;
@ -49,6 +50,7 @@ import static org.mockito.Mockito.mock;
* @author Andy Wilkinson
* @author Chris Bono
*/
@Servlet5ClassPathOverrides
class JettyMetricsAutoConfigurationTests {
@Test

View File

@ -31,9 +31,7 @@ dependencies {
}
optional("io.r2dbc:r2dbc-pool")
optional("io.r2dbc:r2dbc-spi")
optional("io.undertow:undertow-servlet-jakarta") {
exclude group: "org.jboss.spec.javax.annotation", module: "jboss-annotations-api_1.3_spec"
}
optional("io.undertow:undertow-servlet")
optional("javax.cache:cache-api")
optional("jakarta.jms:jakarta.jms-api")
optional("org.apache.tomcat.embed:tomcat-embed-core")

View File

@ -36,12 +36,8 @@ dependencies {
optional("io.r2dbc:r2dbc-pool")
optional("io.rsocket:rsocket-core")
optional("io.rsocket:rsocket-transport-netty")
optional("io.undertow:undertow-servlet-jakarta") {
exclude group: "org.jboss.spec.javax.annotation", module: "jboss-annotations-api_1.3_spec"
}
optional("io.undertow:undertow-websockets-jsr-jakarta") {
exclude group: "org.jboss.spec.javax.annotation", module: "jboss-annotations-api_1.3_spec"
}
optional("io.undertow:undertow-servlet")
optional("io.undertow:undertow-websockets-jsr")
optional("jakarta.jms:jakarta.jms-api")
optional("jakarta.mail:jakarta.mail-api")
optional("jakarta.json.bind:jakarta.json.bind-api")

View File

@ -51,6 +51,8 @@ import org.springframework.boot.context.properties.bind.Bindable;
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.testsupport.web.servlet.Servlet5ClassPathOverrides;
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.web.embedded.jetty.JettyWebServer;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
@ -84,6 +86,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Chris Bono
* @author Parviz Rozikov
*/
@DirtiesUrlFactories
class ServerPropertiesTests {
private final ServerProperties properties = new ServerProperties();
@ -458,6 +461,7 @@ class ServerPropertiesTests {
}
@Test
@Servlet5ClassPathOverrides
void jettyThreadPoolPropertyDefaultsShouldMatchServerDefault() {
JettyServletWebServerFactory jettyFactory = new JettyServletWebServerFactory(0);
JettyWebServer jetty = (JettyWebServer) jettyFactory.getWebServer();
@ -472,6 +476,7 @@ class ServerPropertiesTests {
}
@Test
@Servlet5ClassPathOverrides
void jettyMaxHttpFormPostSizeMatchesDefault() {
JettyServletWebServerFactory jettyFactory = new JettyServletWebServerFactory(0);
JettyWebServer jetty = (JettyWebServer) jettyFactory

View File

@ -45,6 +45,8 @@ import org.springframework.boot.autoconfigure.web.ServerProperties.Jetty;
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.testsupport.web.servlet.Servlet5ClassPathOverrides;
import org.springframework.boot.web.embedded.jetty.ConfigurableJettyWebServerFactory;
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.web.embedded.jetty.JettyWebServer;
@ -63,6 +65,8 @@ import static org.mockito.Mockito.mock;
* @author Phillip Webb
* @author HaiTao Zhang
*/
@DirtiesUrlFactories
@Servlet5ClassPathOverrides
class JettyWebServerFactoryCustomizerTests {
private MockEnvironment environment;

View File

@ -28,6 +28,8 @@ import reactor.netty.http.server.HttpServer;
import org.springframework.boot.autoconfigure.AutoConfigurations;
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.testsupport.web.servlet.Servlet5ClassPathOverrides;
import org.springframework.boot.web.embedded.jetty.JettyReactiveWebServerFactory;
import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer;
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
@ -63,6 +65,7 @@ import static org.mockito.Mockito.mock;
* @author Raheela Aslam
* @author Madhura Bhave
*/
@DirtiesUrlFactories
class ReactiveWebServerFactoryAutoConfigurationTests {
private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner(
@ -215,6 +218,7 @@ class ReactiveWebServerFactoryAutoConfigurationTests {
}
@Test
@Servlet5ClassPathOverrides
void jettyServerCustomizerBeanIsAddedToFactory() {
new ReactiveWebApplicationContextRunner(AnnotationConfigReactiveWebApplicationContext::new)
.withConfiguration(AutoConfigurations.of(ReactiveWebServerFactoryAutoConfiguration.class))
@ -227,6 +231,7 @@ class ReactiveWebServerFactoryAutoConfigurationTests {
}
@Test
@Servlet5ClassPathOverrides
void jettyServerCustomizerRegisteredAsBeanAndViaFactoryIsOnlyCalledOnce() {
new ReactiveWebApplicationContextRunner(AnnotationConfigReactiveWebServerApplicationContext::new)
.withConfiguration(AutoConfigurations.of(ReactiveWebServerFactoryAutoConfiguration.class))

View File

@ -31,6 +31,7 @@ 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.testsupport.web.servlet.Servlet5ClassPathOverrides;
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
@ -219,6 +220,7 @@ class MultipartAutoConfigurationTests {
}
@Servlet5ClassPathOverrides
@Configuration(proxyBeanMethods = false)
static class WebServerWithNoMultipartJetty {
@ -279,6 +281,7 @@ class MultipartAutoConfigurationTests {
}
@Servlet5ClassPathOverrides
@Configuration(proxyBeanMethods = false)
static class WebServerWithEverythingJetty {

View File

@ -37,6 +37,8 @@ import org.springframework.boot.test.context.FilteredClassLoader;
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.testsupport.web.servlet.DirtiesUrlFactories;
import org.springframework.boot.testsupport.web.servlet.Servlet5ClassPathOverrides;
import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer;
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
@ -76,6 +78,7 @@ import static org.mockito.Mockito.mock;
* @author Raheela Aslam
* @author Madhura Bhave
*/
@DirtiesUrlFactories
class ServletWebServerFactoryAutoConfigurationTests {
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner(
@ -151,6 +154,7 @@ class ServletWebServerFactoryAutoConfigurationTests {
}
@Test
@Servlet5ClassPathOverrides
void jettyServerCustomizerBeanIsAddedToFactory() {
WebApplicationContextRunner runner = new WebApplicationContextRunner(
AnnotationConfigServletWebServerApplicationContext::new)
@ -165,6 +169,7 @@ class ServletWebServerFactoryAutoConfigurationTests {
}
@Test
@Servlet5ClassPathOverrides
void jettyServerCustomizerRegisteredAsBeanAndViaFactoryIsOnlyCalledOnce() {
WebApplicationContextRunner runner = new WebApplicationContextRunner(
AnnotationConfigServletWebServerApplicationContext::new)
@ -410,7 +415,7 @@ class ServletWebServerFactoryAutoConfigurationTests {
void relativeRedirectsShouldNotBeEnabledWhenNotUsingTomcatContainer() {
WebApplicationContextRunner runner = new WebApplicationContextRunner(
AnnotationConfigServletWebServerApplicationContext::new)
.withClassLoader(new FilteredClassLoader(Tomcat.class))
.withClassLoader(new FilteredClassLoader(Tomcat.class, Server.class))
.withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class))
.withPropertyValues("server.forward-headers-strategy=framework", "server.port=0");
runner.run((context) -> {

View File

@ -98,6 +98,7 @@ class ServletWebServerFactoryCustomizerTests {
}
@Test
@SuppressWarnings("removal")
void customizeSessionProperties() {
Map<String, String> map = new HashMap<>();
map.put("server.servlet.session.timeout", "123");

View File

@ -24,7 +24,9 @@ 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.testsupport.web.servlet.Servlet5ClassPathOverrides;
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
@ -49,6 +51,7 @@ class ServletWebServerServletContextListenerTests {
@ParameterizedTest(name = "{0}")
@MethodSource("testConfiguration")
@ForkedClassPath
void registeredServletContextListenerBeanIsCalled(String serverName, Class<?> configuration) {
AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext(
ServletListenerRegistrationBeanConfiguration.class, configuration);
@ -60,6 +63,7 @@ class ServletWebServerServletContextListenerTests {
@ParameterizedTest(name = "{0}")
@MethodSource("testConfiguration")
@ForkedClassPath
void servletContextListenerBeanIsCalled(String serverName, Class<?> configuration) {
AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext(
ServletContextListenerBeanConfiguration.class, configuration);
@ -85,6 +89,7 @@ class ServletWebServerServletContextListenerTests {
}
@Servlet5ClassPathOverrides
@Configuration(proxyBeanMethods = false)
static class JettyConfiguration {

View File

@ -23,7 +23,9 @@ 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.testsupport.web.servlet.Servlet5ClassPathOverrides;
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor;
@ -44,6 +46,7 @@ class WebSocketServletAutoConfigurationTests {
@ParameterizedTest(name = "{0}")
@MethodSource("testConfiguration")
@ForkedClassPath
void serverContainerIsAvailableFromTheServletContext(String server, Class<?>... configuration) {
try (AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext(
configuration)) {
@ -84,6 +87,7 @@ class WebSocketServletAutoConfigurationTests {
}
@Servlet5ClassPathOverrides
@Configuration(proxyBeanMethods = false)
static class JettyConfiguration extends CommonConfiguration {

View File

@ -272,10 +272,7 @@ bom {
]
}
}
library("Glassfish JSTL", "2.0.0") {
prohibit("[3.0.0,)") {
because "it exceeds our Jakarta EE 9 baseline"
}
library("Glassfish JSTL", "3.0.0") {
group("org.glassfish.web") {
modules = [
"jakarta.servlet.jsp.jstl"
@ -535,20 +532,14 @@ bom {
]
}
}
library("Jakarta Servlet", "5.0.0") {
prohibit("[6.0.0,)") {
because "it exceeds our Jakarta EE 9 baseline"
}
library("Jakarta Servlet", "6.0.0") {
group("jakarta.servlet") {
modules = [
"jakarta.servlet-api"
]
}
}
library("Jakarta Servlet JSP JSTL", "2.0.0") {
prohibit("[3.0.0,)") {
because "it exceeds our Jakarta EE 9 baseline"
}
library("Jakarta Servlet JSP JSTL", "3.0.0") {
group("jakarta.servlet.jsp.jstl") {
modules = [
"jakarta.servlet.jsp.jstl-api"
@ -569,20 +560,15 @@ bom {
]
}
}
library("Jakarta WebSocket", "2.0.0") {
prohibit("[2.1.0,)") {
because "it exceeds our Jakarta EE 9 baseline"
}
library("Jakarta WebSocket", "2.1.0") {
group("jakarta.websocket") {
modules = [
"jakarta.websocket-api"
"jakarta.websocket-api",
"jakarta.websocket-client-api"
]
}
}
library("Jakarta WS RS", "3.0.0") {
prohibit("[3.1.0,)") {
because "it exceeds our Jakarta EE 9 baseline"
}
library("Jakarta WS RS", "3.1.0") {
group("jakarta.ws.rs") {
modules = [
"jakarta.ws.rs-api"
@ -677,7 +663,7 @@ bom {
]
}
}
library("Jersey", "3.0.8") {
library("Jersey", "3.1.0") {
group("org.glassfish.jersey") {
imports = [
"jersey-bom"
@ -1563,12 +1549,12 @@ bom {
]
}
}
library("Undertow", "2.2.20.Final") {
library("Undertow", "2.3.0.Final") {
group("io.undertow") {
modules = [
"undertow-core",
"undertow-servlet-jakarta",
"undertow-websockets-jsr-jakarta"
"undertow-servlet",
"undertow-websockets-jsr"
]
}
}

View File

@ -7,6 +7,7 @@ description = "Starter for using Jetty as the embedded servlet container. An alt
dependencies {
api("jakarta.servlet:jakarta.servlet-api")
api("jakarta.websocket:jakarta.websocket-api")
api("jakarta.websocket:jakarta.websocket-client-api")
api("org.apache.tomcat.embed:tomcat-embed-el")
api("org.eclipse.jetty:jetty-servlets")
api("org.eclipse.jetty:jetty-webapp") {

View File

@ -6,8 +6,7 @@ description = "Starter for using Undertow as the embedded servlet container. An
dependencies {
api("io.undertow:undertow-core")
api("io.undertow:undertow-servlet-jakarta")
api("io.undertow:undertow-websockets-jsr-jakarta")
api("jakarta.websocket:jakarta.websocket-api")
api("io.undertow:undertow-servlet")
api("io.undertow:undertow-websockets-jsr")
api("org.apache.tomcat.embed:tomcat-embed-el")
}

View File

@ -62,7 +62,7 @@ class JarIntegrationTests extends AbstractArchiveIntegrationTests {
}).hasEntryWithNameStartingWith("BOOT-INF/lib/spring-context")
.hasEntryWithNameStartingWith("BOOT-INF/lib/spring-core")
.hasEntryWithNameStartingWith("BOOT-INF/lib/spring-jcl")
.hasEntryWithNameStartingWith("BOOT-INF/lib/jakarta.servlet-api-5")
.hasEntryWithNameStartingWith("BOOT-INF/lib/jakarta.servlet-api-6")
.hasEntryWithName("BOOT-INF/classes/org/test/SampleApplication.class")
.hasEntryWithName("org/springframework/boot/loader/JarLauncher.class");
assertThat(buildLog(project)).contains("Replacing main artifact with repackaged archive")

View File

@ -55,7 +55,7 @@ class WarIntegrationTests extends AbstractArchiveIntegrationTests {
.hasEntryWithNameStartingWith("WEB-INF/lib/spring-context")
.hasEntryWithNameStartingWith("WEB-INF/lib/spring-core")
.hasEntryWithNameStartingWith("WEB-INF/lib/spring-jcl")
.hasEntryWithNameStartingWith("WEB-INF/lib-provided/jakarta.servlet-api-5")
.hasEntryWithNameStartingWith("WEB-INF/lib-provided/jakarta.servlet-api-6")
.hasEntryWithName("org/springframework/boot/loader/WarLauncher.class")
.hasEntryWithName("WEB-INF/classes/org/test/SampleApplication.class")
.hasEntryWithName("index.html")

View File

@ -0,0 +1,41 @@
/*
* Copyright 2012-2022 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.testsupport.web.servlet;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
import org.springframework.boot.testsupport.classpath.ClassPathOverrides;
/**
* Annotation to downgrade to Servlet 5.0.
*
* @author Phillip Webb
* @since 3.0.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@ClassPathExclusions("jakarta.servlet-api-6*.jar")
@ClassPathOverrides("jakarta.servlet:jakarta.servlet-api:5.0.0")
public @interface Servlet5ClassPathOverrides {
}

View File

@ -36,9 +36,7 @@ dependencies {
optional("io.r2dbc:r2dbc-pool")
optional("io.rsocket:rsocket-core")
optional("io.rsocket:rsocket-transport-netty")
optional("io.undertow:undertow-servlet-jakarta") {
exclude group: "org.jboss.spec.javax.annotation", module: "jboss-annotations-api_1.3_spec"
}
optional("io.undertow:undertow-servlet")
optional("jakarta.jms:jakarta.jms-api")
optional("jakarta.persistence:jakarta.persistence-api")
optional("jakarta.servlet:jakarta.servlet-api")

View File

@ -693,6 +693,7 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor
}
@Override
@SuppressWarnings("removal")
public void addCookie(Cookie cookie) {
SameSite sameSite = getSameSite(cookie);
if (sameSite != null) {

View File

@ -112,6 +112,7 @@ final class TldPatterns {
skipPatterns.add("tomcat-websocket.jar");
skipPatterns.add("tools.jar");
skipPatterns.add("websocket-api.jar");
skipPatterns.add("websocket-client-api.jar");
skipPatterns.add("wsdl4j*.jar");
skipPatterns.add("xercesImpl.jar");
skipPatterns.add("xml-apis.jar");

View File

@ -639,6 +639,7 @@ public class UndertowServletWebServerFactory extends AbstractServletWebServerFac
}
}
@SuppressWarnings("removal")
private jakarta.servlet.http.Cookie asServletCookie(Cookie cookie) {
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
jakarta.servlet.http.Cookie result = new jakarta.servlet.http.Cookie(cookie.getName(), cookie.getValue());

View File

@ -335,6 +335,7 @@ public abstract class AbstractServletWebServerFactory extends AbstractConfigurab
configureSessionCookie(servletContext.getSessionCookieConfig());
}
@SuppressWarnings("removal")
private void configureSessionCookie(SessionCookieConfig config) {
Session.Cookie cookie = this.session.getCookie();
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();

View File

@ -21,6 +21,7 @@ import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.Set;
import org.springframework.boot.context.properties.DeprecatedConfigurationProperty;
import org.springframework.boot.convert.DurationUnit;
/**
@ -113,11 +114,15 @@ public class Session {
/**
* Return the comment for the session cookie.
* @return the session cookie comment
* @deprecated since 3.0.0 without replacement
*/
@Deprecated(since = "3.0.0", forRemoval = true)
@DeprecatedConfigurationProperty
public String getComment() {
return this.comment;
}
@Deprecated(since = "3.0.0", forRemoval = true)
public void setComment(String comment) {
this.comment = comment;
}

View File

@ -29,6 +29,7 @@ import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.mockito.InOrder;
import org.springframework.boot.testsupport.web.servlet.Servlet5ClassPathOverrides;
import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactoryTests;
import org.springframework.boot.web.server.Shutdown;
import org.springframework.http.client.reactive.JettyResourceFactory;
@ -47,6 +48,7 @@ import static org.mockito.Mockito.mock;
* @author Brian Clozel
* @author Madhura Bhave
*/
@Servlet5ClassPathOverrides
class JettyReactiveWebServerFactoryTests extends AbstractReactiveWebServerFactoryTests {
@Override

View File

@ -61,6 +61,7 @@ import org.junit.jupiter.api.Test;
import org.mockito.InOrder;
import org.springframework.boot.testsupport.system.CapturedOutput;
import org.springframework.boot.testsupport.web.servlet.Servlet5ClassPathOverrides;
import org.springframework.boot.web.server.Compression;
import org.springframework.boot.web.server.GracefulShutdownResult;
import org.springframework.boot.web.server.PortInUseException;
@ -86,6 +87,7 @@ import static org.mockito.Mockito.mock;
* @author Andy Wilkinson
* @author Henri Kerola
*/
@Servlet5ClassPathOverrides
class JettyServletWebServerFactoryTests extends AbstractServletWebServerFactoryTests {
@Override
@ -142,7 +144,6 @@ class JettyServletWebServerFactoryTests extends AbstractServletWebServerFactoryT
@Override
@Disabled("Jetty 11 does not support User-Agent-based compression")
protected void noCompressionForUserAgent() {
}
@Test

View File

@ -69,6 +69,7 @@ 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.ArgumentCaptor;
import org.mockito.InOrder;
@ -119,6 +120,11 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
}
@Override
protected boolean isCookieCommentSupported() {
return false;
}
// JMX MBean names clash if you get more than one Engine with the same name...
@Test
void tomcatEngineNames() {
@ -418,6 +424,7 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory
}
@Test
@Disabled("See https://github.com/apache/tomcat/commit/c3e33b62101c5ee155808dd1932acde0cac65fe3")
void sessionIdGeneratorIsConfiguredWithAttributesFromTheManager() {
System.setProperty("jvmRoute", "test");
try {

View File

@ -36,6 +36,9 @@ import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
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.testsupport.web.servlet.Servlet5ClassPathOverrides;
import org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer;
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
@ -55,6 +58,7 @@ import static org.assertj.core.api.Assertions.assertThat;
*
* @author Andy Wilkinson
*/
@DirtiesUrlFactories
class ServletComponentScanIntegrationTests {
private AnnotationConfigServletWebServerApplicationContext context;
@ -71,6 +75,7 @@ class ServletComponentScanIntegrationTests {
@ParameterizedTest(name = "{0}")
@MethodSource("testConfiguration")
@ForkedClassPath
void componentsAreRegistered(String serverName, Class<?> configuration) {
this.context = new AnnotationConfigServletWebServerApplicationContext();
this.context.register(configuration);
@ -83,6 +88,7 @@ class ServletComponentScanIntegrationTests {
@ParameterizedTest(name = "{0}")
@MethodSource("testConfiguration")
@ForkedClassPath
void indexedComponentsAreRegistered(String serverName, Class<?> configuration) throws IOException {
writeIndex(this.temp);
this.context = new AnnotationConfigServletWebServerApplicationContext();
@ -100,6 +106,7 @@ class ServletComponentScanIntegrationTests {
@ParameterizedTest(name = "{0}")
@MethodSource("testConfiguration")
@ForkedClassPath
void multipartConfigIsHonoured(String serverName, Class<?> configuration) {
this.context = new AnnotationConfigServletWebServerApplicationContext();
this.context.register(configuration);
@ -152,6 +159,7 @@ class ServletComponentScanIntegrationTests {
}
@Configuration(proxyBeanMethods = false)
@Servlet5ClassPathOverrides
static class JettyTestConfiguration extends AbstractTestConfiguration {
@Override

View File

@ -21,6 +21,8 @@ import java.net.URI;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories;
import org.springframework.boot.testsupport.web.servlet.Servlet5ClassPathOverrides;
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
@ -51,6 +53,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Phillip Webb
* @author Ivan Sopov
*/
@DirtiesUrlFactories
class ServletWebServerMvcIntegrationTests {
private AnnotationConfigServletWebServerApplicationContext context;
@ -72,6 +75,7 @@ class ServletWebServerMvcIntegrationTests {
}
@Test
@Servlet5ClassPathOverrides
void jetty() throws Exception {
this.context = new AnnotationConfigServletWebServerApplicationContext(JettyConfig.class);
doTest(this.context, "/hello");
@ -84,6 +88,7 @@ class ServletWebServerMvcIntegrationTests {
}
@Test
@Servlet5ClassPathOverrides
void advancedConfig() throws Exception {
this.context = new AnnotationConfigServletWebServerApplicationContext(AdvancedConfig.class);
doTest(this.context, "/example/spring/hello");

View File

@ -196,6 +196,10 @@ public abstract class AbstractServletWebServerFactoryTests {
}
}
protected boolean isCookieCommentSupported() {
return true;
}
@Test
void startServlet() throws Exception {
AbstractServletWebServerFactory factory = getFactory();
@ -792,6 +796,7 @@ public abstract class AbstractServletWebServerFactoryTests {
}
@Test
@SuppressWarnings("removal")
void sessionCookieConfiguration() {
AbstractServletWebServerFactory factory = getFactory();
factory.getSession().getCookie().setName("testname");
@ -807,7 +812,9 @@ public abstract class AbstractServletWebServerFactoryTests {
assertThat(sessionCookieConfig.getName()).isEqualTo("testname");
assertThat(sessionCookieConfig.getDomain()).isEqualTo("testdomain");
assertThat(sessionCookieConfig.getPath()).isEqualTo("/testpath");
assertThat(sessionCookieConfig.getComment()).isEqualTo("testcomment");
if (isCookieCommentSupported()) {
assertThat(sessionCookieConfig.getComment()).isEqualTo("testcomment");
}
assertThat(sessionCookieConfig.isHttpOnly()).isTrue();
assertThat(sessionCookieConfig.isSecure()).isTrue();
assertThat(sessionCookieConfig.getMaxAge()).isEqualTo(60);
@ -1062,6 +1069,7 @@ public abstract class AbstractServletWebServerFactoryTests {
}
@Test
@SuppressWarnings("removal")
void sessionConfiguration() {
AbstractServletWebServerFactory factory = getFactory();
factory.getSession().setTimeout(Duration.ofSeconds(123));
@ -1081,7 +1089,9 @@ public abstract class AbstractServletWebServerFactoryTests {
assertThat(servletContext.getSessionCookieConfig().getName()).isEqualTo("testname");
assertThat(servletContext.getSessionCookieConfig().getDomain()).isEqualTo("testdomain");
assertThat(servletContext.getSessionCookieConfig().getPath()).isEqualTo("/testpath");
assertThat(servletContext.getSessionCookieConfig().getComment()).isEqualTo("testcomment");
if (isCookieCommentSupported()) {
assertThat(servletContext.getSessionCookieConfig().getComment()).isEqualTo("testcomment");
}
assertThat(servletContext.getSessionCookieConfig().isHttpOnly()).isTrue();
assertThat(servletContext.getSessionCookieConfig().isSecure()).isTrue();
assertThat(servletContext.getSessionCookieConfig().getMaxAge()).isEqualTo(60);

View File

@ -27,9 +27,26 @@ repositories {
}
configurations {
jetty
tomcat
undertow
app {
extendsFrom(configurations.runtimeClasspath)
}
jetty {
extendsFrom(app)
}
tomcat {
extendsFrom(app)
}
undertow {
extendsFrom(app)
}
}
dependencyManagement {
jetty {
dependencies {
dependency "jakarta.servlet:jakarta.servlet-api:5.0.0"
}
}
}
tasks.register("resourcesJar", Jar) { jar ->
@ -50,30 +67,30 @@ tasks.register("resourcesJar", Jar) { jar ->
dependencies {
compileOnly("org.eclipse.jetty:jetty-server")
compileOnly("org.springframework:spring-web")
implementation("org.springframework.boot:spring-boot-starter")
implementation("org.springframework:spring-web")
app(files(resourcesJar))
app(files(sourceSets.main.output))
app("org.springframework:spring-web")
jetty("org.springframework.boot:spring-boot-starter-jetty")
jetty files(resourcesJar)
tomcat("org.springframework.boot:spring-boot-starter-tomcat")
tomcat files(resourcesJar)
undertow("org.springframework.boot:spring-boot-starter-undertow")
undertow files(resourcesJar)
}
def boolean isWindows() {
return File.separatorChar == '\\';
}
["jetty", "tomcat", "undertow"].each { container ->
["jetty", "tomcat", "undertow"].each { webServer ->
def configurer = { task ->
task.dependsOn resourcesJar
task.mainClass = "com.example.ResourceHandlingApplication"
task.classpath = sourceSets.main.runtimeClasspath.plus(configurations.getByName(container))
task.classifier = container
task.classpath = configurations.getByName(webServer)
task.classifier = webServer
task.targetJavaVersion = project.getTargetCompatibility()
}
tasks.register("${container}BootJar", BootJar, configurer)
tasks.register("${container}BootWar", BootWar, configurer)
tasks.register("${webServer}BootJar", BootJar, configurer)
tasks.register("${webServer}BootWar", BootWar, configurer)
}

View File

@ -11,6 +11,10 @@ configurations {
}
}
configurations.all {
resolutionStrategy.force("jakarta.servlet:jakarta.servlet-api:5.0.0")
}
dependencies {
compileOnly(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-jetty"))

View File

@ -5,6 +5,10 @@ plugins {
description = "Spring Boot Jetty SSL smoke test"
configurations.all {
resolutionStrategy.force("jakarta.servlet:jakarta.servlet-api:5.0.0")
}
dependencies {
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-jetty"))
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-web")) {

View File

@ -5,6 +5,10 @@ plugins {
description = "Spring Boot Jetty smoke test"
configurations.all {
resolutionStrategy.force("jakarta.servlet:jakarta.servlet-api:5.0.0")
}
dependencies {
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-web")) {
exclude module: "spring-boot-starter-tomcat"

View File

@ -5,6 +5,10 @@ plugins {
description = "Spring Boot WebSocket Jetty smoke test"
configurations.all {
resolutionStrategy.force("jakarta.servlet:jakarta.servlet-api:5.0.0")
}
dependencies {
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-jetty"))
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-websocket")) {