Skip to content

Commit

Permalink
Align with Servlet 6.0 and introduce support for Jakarta WebSocket 2.1
Browse files Browse the repository at this point in the history
Includes corresponding build upgrade to Tomcat 10.1.1 and Undertow 2.3.0
(while retaining runtime compatibility with Tomcat 10.0 and Undertow 2.2)

Closes gh-29435
Closes gh-29436
  • Loading branch information
jhoeller committed Nov 6, 2022
1 parent 4b22a4a commit 19cf503
Show file tree
Hide file tree
Showing 37 changed files with 289 additions and 340 deletions.
7 changes: 4 additions & 3 deletions framework-docs/src/docs/asciidoc/overview.adoc
Expand Up @@ -78,9 +78,10 @@ by the Spring Framework. Originally, those were based on common `javax` packages

As of Spring Framework 6.0, Spring has been upgraded to the Jakarta EE 9 level
(e.g. Servlet 5.0+, JPA 3.0+), based on the `jakarta` namespace instead of the
traditional `javax` packages. With EE 9 as the minimum, Spring is prepared to
provide out-of-the-box support for further API evolution in EE 10+ once available.
This makes Spring Framework 6 fully compatible with e.g. Tomcat 10+ and Jetty 11+.
traditional `javax` packages. With EE 9 as the minimum and EE 10 supported already,
Spring is prepared to provide out-of-the-box support for the further evolution of
the Jakarta EE APIs. Spring Framework 6.0 is fully compatible with Tomcat 10.1,
Jetty 11 and Undertow 2.3 as web servers, and also with Hibernate ORM 6.1.

Over time, the role of Java/Jakarta EE in application development has evolved. In the
early days of J2EE and Spring, applications were created to be deployed to an application
Expand Down
27 changes: 14 additions & 13 deletions framework-platform/framework-platform.gradle
Expand Up @@ -54,9 +54,9 @@ dependencies {
api("io.r2dbc:r2dbc-spi:1.0.0.RELEASE")
api("io.reactivex.rxjava3:rxjava:3.1.5")
api("io.smallrye.reactive:mutiny:1.7.0")
api("io.undertow:undertow-core:2.2.19.Final")
api("io.undertow:undertow-servlet-jakarta:2.2.19.Final")
api("io.undertow:undertow-websockets-jsr-jakarta:2.2.19.Final")
api("io.undertow:undertow-core:2.3.0.Final")
api("io.undertow:undertow-servlet:2.3.0.Final")
api("io.undertow:undertow-websockets-jsr:2.3.0.Final")
api("io.vavr:vavr:0.10.4")
api("jakarta.activation:jakarta.activation-api:2.0.1")
api("jakarta.annotation:jakarta.annotation-api:2.0.0")
Expand All @@ -73,12 +73,13 @@ dependencies {
api("jakarta.mail:jakarta.mail-api:2.0.1")
api("jakarta.persistence:jakarta.persistence-api:3.0.0")
api("jakarta.resource:jakarta.resource-api:2.0.0")
api("jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api:2.0.0")
api("jakarta.servlet.jsp:jakarta.servlet.jsp-api:3.0.0")
api("jakarta.servlet:jakarta.servlet-api:5.0.0")
api("jakarta.transaction:jakarta.transaction-api:2.0.0")
api("jakarta.validation:jakarta.validation-api:3.0.0")
api("jakarta.websocket:jakarta.websocket-api:2.0.0")
api("jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api:3.0.0")
api("jakarta.servlet.jsp:jakarta.servlet.jsp-api:3.1.0")
api("jakarta.servlet:jakarta.servlet-api:6.0.0")
api("jakarta.transaction:jakarta.transaction-api:2.0.1")
api("jakarta.validation:jakarta.validation-api:3.0.2")
api("jakarta.websocket:jakarta.websocket-api:2.1.0")
api("jakarta.websocket:jakarta.websocket-client-api:2.1.0")
api("jakarta.xml.bind:jakarta.xml.bind-api:3.0.1")
api("javax.cache:cache-api:1.1.1")
api("javax.money:money-api:1.1")
Expand All @@ -97,10 +98,10 @@ dependencies {
api("org.apache.httpcomponents.client5:httpclient5:5.1.3")
api("org.apache.httpcomponents.core5:httpcore5-reactive:5.1.3")
api("org.apache.poi:poi-ooxml:5.2.2")
api("org.apache.tomcat.embed:tomcat-embed-core:10.1.0")
api("org.apache.tomcat.embed:tomcat-embed-websocket:10.1.0")
api("org.apache.tomcat:tomcat-util:10.0.22")
api("org.apache.tomcat:tomcat-websocket:10.0.22")
api("org.apache.tomcat.embed:tomcat-embed-core:10.1.1")
api("org.apache.tomcat.embed:tomcat-embed-websocket:10.1.1")
api("org.apache.tomcat:tomcat-util:10.1.1")
api("org.apache.tomcat:tomcat-websocket:10.1.1")
api("org.aspectj:aspectjrt:1.9.9.1")
api("org.aspectj:aspectjtools:1.9.9.1")
api("org.aspectj:aspectjweaver:1.9.9.1")
Expand Down
3 changes: 2 additions & 1 deletion spring-test/spring-test.gradle
Expand Up @@ -23,9 +23,10 @@ dependencies {
optional("jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api")
optional("jakarta.xml.bind:jakarta.xml.bind-api")
optional("jakarta.websocket:jakarta.websocket-api")
optional("jakarta.websocket:jakarta.websocket-client-api")
optional("junit:junit")
optional("org.apache.tomcat.embed:tomcat-embed-core")
optional("org.junit.platform:junit-platform-launcher") // for AOT processing
optional("org.junit.platform:junit-platform-launcher") // for AOT processing
optional("org.junit.jupiter:junit-jupiter-api")
optional("org.testng:testng")
optional("org.aspectj:aspectjweaver")
Expand Down
Expand Up @@ -36,6 +36,7 @@
* @author Sam Brannen
* @since 5.1
*/
@SuppressWarnings("removal")
public class MockCookie extends Cookie {

private static final long serialVersionUID = 4312531139502726325L;
Expand Down
Expand Up @@ -46,6 +46,7 @@
import jakarta.servlet.AsyncContext;
import jakarta.servlet.DispatcherType;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletConnection;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletInputStream;
Expand Down Expand Up @@ -79,7 +80,7 @@
* is {@link Locale#ENGLISH}. This value can be changed via {@link #addPreferredLocale}
* or {@link #setPreferredLocales}.
*
* <p>As of Spring Framework 5.0, this set of mocks is designed on a Servlet 4.0 baseline.
* <p>As of Spring 6.0, this set of mocks is designed on a Servlet 6.0 baseline.
*
* @author Juergen Hoeller
* @author Rod Johnson
Expand Down Expand Up @@ -878,12 +879,6 @@ public RequestDispatcher getRequestDispatcher(String path) {
return new MockRequestDispatcher(path);
}

@Override
@Deprecated
public String getRealPath(String path) {
return this.servletContext.getRealPath(path);
}

public void setRemotePort(int remotePort) {
this.remotePort = remotePort;
}
Expand Down Expand Up @@ -970,6 +965,38 @@ public DispatcherType getDispatcherType() {
return this.dispatcherType;
}

@Override
public String getRequestId() {
return "";
}

@Override
public String getProtocolRequestId() {
return "";
}

@Override
public ServletConnection getServletConnection() {
return new ServletConnection() {
@Override
public String getConnectionId() {
return MockHttpServletRequest.this.getRequestId();
}
@Override
public String getProtocol() {
return MockHttpServletRequest.this.getProtocol();
}
@Override
public String getProtocolConnectionId() {
return MockHttpServletRequest.this.getProtocolRequestId();
}
@Override
public boolean isSecure() {
return MockHttpServletRequest.this.isSecure();
}
};
}


// ---------------------------------------------------------------------
// HttpServletRequest interface
Expand Down Expand Up @@ -1183,7 +1210,7 @@ public String getPathInfo() {
@Override
@Nullable
public String getPathTranslated() {
return (this.pathInfo != null ? getRealPath(this.pathInfo) : null);
return (this.pathInfo != null ? this.servletContext.getRealPath(this.pathInfo) : null);
}

public void setContextPath(String contextPath) {
Expand Down Expand Up @@ -1352,12 +1379,6 @@ public boolean isRequestedSessionIdFromURL() {
return this.requestedSessionIdFromURL;
}

@Override
@Deprecated
public boolean isRequestedSessionIdFromUrl() {
return isRequestedSessionIdFromURL();
}

@Override
public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {
throw new UnsupportedOperationException();
Expand Down
Expand Up @@ -53,7 +53,7 @@
/**
* Mock implementation of the {@link jakarta.servlet.http.HttpServletResponse} interface.
*
* <p>As of Spring Framework 5.0, this set of mocks is designed on a Servlet 4.0 baseline.
* <p>As of Spring 6.0, this set of mocks is designed on a Servlet 6.0 baseline.
*
* @author Juergen Hoeller
* @author Rod Johnson
Expand Down Expand Up @@ -413,6 +413,7 @@ public void addCookie(Cookie cookie) {
doAddHeaderValue(HttpHeaders.SET_COOKIE, getCookieHeader(cookie), false);
}

@SuppressWarnings("removal")
private String getCookieHeader(Cookie cookie) {
StringBuilder buf = new StringBuilder();
buf.append(cookie.getName()).append('=').append(cookie.getValue() == null ? "" : cookie.getValue());
Expand Down Expand Up @@ -572,18 +573,6 @@ public String encodeRedirectURL(String url) {
return encodeURL(url);
}

@Override
@Deprecated
public String encodeUrl(String url) {
return encodeURL(url);
}

@Override
@Deprecated
public String encodeRedirectUrl(String url) {
return encodeRedirectURL(url);
}

@Override
public void sendError(int status, String errorMessage) throws IOException {
Assert.state(!isCommitted(), "Cannot set error status - response is already committed");
Expand Down Expand Up @@ -758,15 +747,6 @@ public void setStatus(int status) {
}
}

@Override
@Deprecated
public void setStatus(int status, String errorMessage) {
if (!this.isCommitted()) {
this.status = status;
this.errorMessage = errorMessage;
}
}

@Override
public int getStatus() {
return this.status;
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-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.
Expand Down Expand Up @@ -32,12 +32,11 @@

import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

/**
* Mock implementation of the {@link jakarta.servlet.http.HttpSession} interface.
*
* <p>As of Spring 5.0, this set of mocks is designed on a Servlet 4.0 baseline.
* <p>As of Spring 6.0, this set of mocks is designed on a Servlet 6.0 baseline.
*
* @author Juergen Hoeller
* @author Rod Johnson
Expand Down Expand Up @@ -148,35 +147,19 @@ public int getMaxInactiveInterval() {
return this.maxInactiveInterval;
}

@Override
public jakarta.servlet.http.HttpSessionContext getSessionContext() {
throw new UnsupportedOperationException("getSessionContext");
}

@Override
public Object getAttribute(String name) {
assertIsValid();
Assert.notNull(name, "Attribute name must not be null");
return this.attributes.get(name);
}

@Override
public Object getValue(String name) {
return getAttribute(name);
}

@Override
public Enumeration<String> getAttributeNames() {
assertIsValid();
return Collections.enumeration(new LinkedHashSet<>(this.attributes.keySet()));
}

@Override
public String[] getValueNames() {
assertIsValid();
return StringUtils.toStringArray(this.attributes.keySet());
}

@Override
public void setAttribute(String name, @Nullable Object value) {
assertIsValid();
Expand All @@ -197,11 +180,6 @@ public void setAttribute(String name, @Nullable Object value) {
}
}

@Override
public void putValue(String name, Object value) {
setAttribute(name, value);
}

@Override
public void removeAttribute(String name) {
assertIsValid();
Expand All @@ -212,11 +190,6 @@ public void removeAttribute(String name) {
}
}

@Override
public void removeValue(String name) {
removeAttribute(name);
}

/**
* Clear all of this session's attributes.
*/
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-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.
Expand Down Expand Up @@ -43,7 +43,7 @@
* Mock implementation of the
* {@link org.springframework.web.multipart.MultipartHttpServletRequest} interface.
*
* <p>As of Spring 5.0, this set of mocks is designed on a Servlet 4.0 baseline.
* <p>As of Spring 6.0, this set of mocks is designed on a Servlet 6.0 baseline.
*
* <p>Useful for testing application controllers that access multipart uploads.
* {@link MockMultipartFile} can be used to populate these mock requests with files.
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-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.
Expand Down Expand Up @@ -60,7 +60,7 @@
/**
* Mock implementation of the {@link jakarta.servlet.ServletContext} interface.
*
* <p>As of Spring 5.0, this set of mocks is designed on a Servlet 4.0 baseline.
* <p>As of Spring 6.0, this set of mocks is designed on a Servlet 6.0 baseline.
*
* <p>Compatible with Servlet 3.1 but can be configured to expose a specific version
* through {@link #setMajorVersion}/{@link #setMinorVersion}; default is 3.1.
Expand Down Expand Up @@ -430,36 +430,11 @@ public void setDefaultServletName(String defaultServletName) {
registerNamedDispatcher(this.defaultServletName, new MockRequestDispatcher(this.defaultServletName));
}

@Deprecated
@Override
@Nullable
public Servlet getServlet(String name) {
return null;
}

@Override
@Deprecated
public Enumeration<Servlet> getServlets() {
return Collections.enumeration(Collections.emptySet());
}

@Override
@Deprecated
public Enumeration<String> getServletNames() {
return Collections.enumeration(Collections.emptySet());
}

@Override
public void log(String message) {
logger.info(message);
}

@Override
@Deprecated
public void log(Exception ex, String message) {
logger.info(message, ex);
}

@Override
public void log(String message, Throwable ex) {
logger.info(message, ex);
Expand Down

0 comments on commit 19cf503

Please sign in to comment.