diff --git a/framework-docs/src/docs/asciidoc/overview.adoc b/framework-docs/src/docs/asciidoc/overview.adoc index fd737bf55b78..33afeb22909b 100644 --- a/framework-docs/src/docs/asciidoc/overview.adoc +++ b/framework-docs/src/docs/asciidoc/overview.adoc @@ -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 diff --git a/framework-platform/framework-platform.gradle b/framework-platform/framework-platform.gradle index 4f155cd927d3..250c7cee142a 100644 --- a/framework-platform/framework-platform.gradle +++ b/framework-platform/framework-platform.gradle @@ -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") @@ -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") @@ -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") diff --git a/spring-test/spring-test.gradle b/spring-test/spring-test.gradle index 320820dd8b62..70263f972a6c 100644 --- a/spring-test/spring-test.gradle +++ b/spring-test/spring-test.gradle @@ -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") diff --git a/spring-test/src/main/java/org/springframework/mock/web/MockCookie.java b/spring-test/src/main/java/org/springframework/mock/web/MockCookie.java index 3dc81d56cd99..ca28a9aa9763 100644 --- a/spring-test/src/main/java/org/springframework/mock/web/MockCookie.java +++ b/spring-test/src/main/java/org/springframework/mock/web/MockCookie.java @@ -36,6 +36,7 @@ * @author Sam Brannen * @since 5.1 */ +@SuppressWarnings("removal") public class MockCookie extends Cookie { private static final long serialVersionUID = 4312531139502726325L; diff --git a/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java b/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java index ec6339e84186..ad730966f0d2 100644 --- a/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java +++ b/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java @@ -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; @@ -79,7 +80,7 @@ * is {@link Locale#ENGLISH}. This value can be changed via {@link #addPreferredLocale} * or {@link #setPreferredLocales}. * - *

As of Spring Framework 5.0, this set of mocks is designed on a Servlet 4.0 baseline. + *

As of Spring 6.0, this set of mocks is designed on a Servlet 6.0 baseline. * * @author Juergen Hoeller * @author Rod Johnson @@ -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; } @@ -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 @@ -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) { @@ -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(); diff --git a/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java b/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java index 1203fe845084..88af4672bfb1 100644 --- a/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java +++ b/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java @@ -53,7 +53,7 @@ /** * Mock implementation of the {@link jakarta.servlet.http.HttpServletResponse} interface. * - *

As of Spring Framework 5.0, this set of mocks is designed on a Servlet 4.0 baseline. + *

As of Spring 6.0, this set of mocks is designed on a Servlet 6.0 baseline. * * @author Juergen Hoeller * @author Rod Johnson @@ -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()); @@ -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"); @@ -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; diff --git a/spring-test/src/main/java/org/springframework/mock/web/MockHttpSession.java b/spring-test/src/main/java/org/springframework/mock/web/MockHttpSession.java index 244880d8d798..e8d1d890e001 100644 --- a/spring-test/src/main/java/org/springframework/mock/web/MockHttpSession.java +++ b/spring-test/src/main/java/org/springframework/mock/web/MockHttpSession.java @@ -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. @@ -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. * - *

As of Spring 5.0, this set of mocks is designed on a Servlet 4.0 baseline. + *

As of Spring 6.0, this set of mocks is designed on a Servlet 6.0 baseline. * * @author Juergen Hoeller * @author Rod Johnson @@ -148,11 +147,6 @@ public int getMaxInactiveInterval() { return this.maxInactiveInterval; } - @Override - public jakarta.servlet.http.HttpSessionContext getSessionContext() { - throw new UnsupportedOperationException("getSessionContext"); - } - @Override public Object getAttribute(String name) { assertIsValid(); @@ -160,23 +154,12 @@ public Object getAttribute(String name) { return this.attributes.get(name); } - @Override - public Object getValue(String name) { - return getAttribute(name); - } - @Override public Enumeration 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(); @@ -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(); @@ -212,11 +190,6 @@ public void removeAttribute(String name) { } } - @Override - public void removeValue(String name) { - removeAttribute(name); - } - /** * Clear all of this session's attributes. */ diff --git a/spring-test/src/main/java/org/springframework/mock/web/MockMultipartHttpServletRequest.java b/spring-test/src/main/java/org/springframework/mock/web/MockMultipartHttpServletRequest.java index 9357c9b58480..aaf0299dd788 100644 --- a/spring-test/src/main/java/org/springframework/mock/web/MockMultipartHttpServletRequest.java +++ b/spring-test/src/main/java/org/springframework/mock/web/MockMultipartHttpServletRequest.java @@ -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. @@ -43,7 +43,7 @@ * Mock implementation of the * {@link org.springframework.web.multipart.MultipartHttpServletRequest} interface. * - *

As of Spring 5.0, this set of mocks is designed on a Servlet 4.0 baseline. + *

As of Spring 6.0, this set of mocks is designed on a Servlet 6.0 baseline. * *

Useful for testing application controllers that access multipart uploads. * {@link MockMultipartFile} can be used to populate these mock requests with files. diff --git a/spring-test/src/main/java/org/springframework/mock/web/MockServletContext.java b/spring-test/src/main/java/org/springframework/mock/web/MockServletContext.java index 736d44168ef1..42f2e7f3e9b8 100644 --- a/spring-test/src/main/java/org/springframework/mock/web/MockServletContext.java +++ b/spring-test/src/main/java/org/springframework/mock/web/MockServletContext.java @@ -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. @@ -60,7 +60,7 @@ /** * Mock implementation of the {@link jakarta.servlet.ServletContext} interface. * - *

As of Spring 5.0, this set of mocks is designed on a Servlet 4.0 baseline. + *

As of Spring 6.0, this set of mocks is designed on a Servlet 6.0 baseline. * *

Compatible with Servlet 3.1 but can be configured to expose a specific version * through {@link #setMajorVersion}/{@link #setMinorVersion}; default is 3.1. @@ -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 getServlets() { - return Collections.enumeration(Collections.emptySet()); - } - - @Override - @Deprecated - public Enumeration 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); diff --git a/spring-test/src/main/java/org/springframework/mock/web/MockSessionCookieConfig.java b/spring-test/src/main/java/org/springframework/mock/web/MockSessionCookieConfig.java index 3a98a87a6027..66b98a3fe347 100644 --- a/spring-test/src/main/java/org/springframework/mock/web/MockSessionCookieConfig.java +++ b/spring-test/src/main/java/org/springframework/mock/web/MockSessionCookieConfig.java @@ -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. @@ -16,6 +16,10 @@ package org.springframework.mock.web; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + import jakarta.servlet.SessionCookieConfig; import org.springframework.lang.Nullable; @@ -47,6 +51,8 @@ public class MockSessionCookieConfig implements SessionCookieConfig { private int maxAge = -1; + private Map attributes = new LinkedHashMap<>(); + @Override public void setName(@Nullable String name) { @@ -81,11 +87,13 @@ public String getPath() { return this.path; } + @SuppressWarnings("removal") @Override public void setComment(@Nullable String comment) { this.comment = comment; } + @SuppressWarnings("removal") @Override @Nullable public String getComment() { @@ -122,4 +130,19 @@ public int getMaxAge() { return this.maxAge; } + @Override + public void setAttribute(String name, String value) { + this.attributes.put(name, value); + } + + @Override + public String getAttribute(String name) { + return this.attributes.get(name); + } + + @Override + public Map getAttributes() { + return Collections.unmodifiableMap(this.attributes); + } + } diff --git a/spring-test/src/main/java/org/springframework/test/context/web/socket/MockServerContainer.java b/spring-test/src/main/java/org/springframework/test/context/web/socket/MockServerContainer.java index cc86220b62d5..e87e453183e4 100644 --- a/spring-test/src/main/java/org/springframework/test/context/web/socket/MockServerContainer.java +++ b/spring-test/src/main/java/org/springframework/test/context/web/socket/MockServerContainer.java @@ -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. @@ -19,6 +19,7 @@ import java.io.IOException; import java.net.URI; import java.util.Collections; +import java.util.Map; import java.util.Set; import jakarta.websocket.ClientEndpointConfig; @@ -133,4 +134,11 @@ public void addEndpoint(ServerEndpointConfig serverConfig) throws DeploymentExce "MockServerContainer does not support addEndpoint(ServerEndpointConfig)"); } + @Override + public void upgradeHttpToWebSocket(Object httpServletRequest, Object httpServletResponse, + ServerEndpointConfig sec, Map pathParameters) throws IOException, DeploymentException { + + throw new UnsupportedOperationException("MockServerContainer does not support upgradeHttpToWebSocket"); + } + } diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebConnection.java b/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebConnection.java index 8b3608772a0d..826d91a3db98 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebConnection.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebConnection.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 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. @@ -173,6 +173,7 @@ private void storeCookies(WebRequest webRequest, jakarta.servlet.http.Cookie[] c } } + @SuppressWarnings("removal") private static com.gargoylesoftware.htmlunit.util.Cookie createCookie(jakarta.servlet.http.Cookie cookie) { Date expires = null; if (cookie.getMaxAge() > -1) { diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/result/CookieResultMatchers.java b/spring-test/src/main/java/org/springframework/test/web/servlet/result/CookieResultMatchers.java index a8a40a29c448..46c8533477e9 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/result/CookieResultMatchers.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/result/CookieResultMatchers.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 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. @@ -149,6 +149,7 @@ public ResultMatcher domain(String name, String domain) { /** * Assert a cookie's comment with a Hamcrest {@link Matcher}. */ + @SuppressWarnings("removal") public ResultMatcher comment(String name, Matcher matcher) { return result -> { Cookie cookie = getCookie(result, name); @@ -159,6 +160,7 @@ public ResultMatcher comment(String name, Matcher matcher) { /** * Assert a cookie's comment. */ + @SuppressWarnings("removal") public ResultMatcher comment(String name, String comment) { return result -> { Cookie cookie = getCookie(result, name); @@ -169,6 +171,7 @@ public ResultMatcher comment(String name, String comment) { /** * Assert a cookie's version with a Hamcrest {@link Matcher}. */ + @SuppressWarnings("removal") public ResultMatcher version(String name, Matcher matcher) { return result -> { Cookie cookie = getCookie(result, name); @@ -179,6 +182,7 @@ public ResultMatcher version(String name, Matcher matcher) { /** * Assert a cookie's version. */ + @SuppressWarnings("removal") public ResultMatcher version(String name, int version) { return result -> { Cookie cookie = getCookie(result, name); diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/result/PrintingResultHandler.java b/spring-test/src/main/java/org/springframework/test/web/servlet/result/PrintingResultHandler.java index fc754a0669b2..bccce3305613 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/result/PrintingResultHandler.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/result/PrintingResultHandler.java @@ -263,6 +263,7 @@ protected void printResponse(MockHttpServletResponse response) throws Exception * {@link Cookie} implementation does not provide its own {@code toString()}. * @since 4.2 */ + @SuppressWarnings("removal") private void printCookies(Cookie[] cookies) { String[] cookieStrings = new String[cookies.length]; for (int i = 0; i < cookies.length; i++) { diff --git a/spring-test/src/test/java/org/springframework/mock/web/MockCookieTests.java b/spring-test/src/test/java/org/springframework/mock/web/MockCookieTests.java index 9cb2247f8eb0..9c14a4f4bf32 100644 --- a/spring-test/src/test/java/org/springframework/mock/web/MockCookieTests.java +++ b/spring-test/src/test/java/org/springframework/mock/web/MockCookieTests.java @@ -65,9 +65,10 @@ void parseHeaderWithoutAttributes() { assertCookie(cookie, "SESSION", "123"); } + @SuppressWarnings("removal") @Test void parseHeaderWithAttributes() { - MockCookie cookie = MockCookie.parse("SESSION=123; Comment=Session Cookie; Domain=example.com; Max-Age=60; " + + MockCookie cookie = MockCookie.parse("SESSION=123; Domain=example.com; Max-Age=60; " + "Expires=Tue, 8 Oct 2019 19:50:00 GMT; Path=/; Secure; HttpOnly; SameSite=Lax"); assertCookie(cookie, "SESSION", "123"); @@ -79,7 +80,7 @@ void parseHeaderWithAttributes() { assertThat(cookie.getExpires()).isEqualTo(ZonedDateTime.parse("Tue, 8 Oct 2019 19:50:00 GMT", DateTimeFormatter.RFC_1123_DATE_TIME)); assertThat(cookie.getSameSite()).isEqualTo("Lax"); - assertThat(cookie.getComment()).isEqualTo("Session Cookie"); + assertThat(cookie.getComment()).isNull(); } @ParameterizedTest diff --git a/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java b/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java index 058d1ae51217..316c30132f2d 100644 --- a/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java +++ b/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java @@ -421,10 +421,9 @@ void modifyStatusAfterSendError() throws IOException { } @Test // SPR-10414 - @SuppressWarnings("deprecation") void modifyStatusMessageAfterSendError() throws IOException { response.sendError(HttpServletResponse.SC_NOT_FOUND); - response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Server Error"); + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_NOT_FOUND); } @@ -474,23 +473,6 @@ void setCookieHeaderWithZeroExpiresAttribute() { assertThat(header).startsWith("SESSION=123; Path=/; Max-Age=100; Expires="); } - /** - * @since 5.3.22 - */ - @Test - void setCookieHeaderWithComment() { - response.setHeader(SET_COOKIE, "SESSION=123;Comment=Test Comment;Path=/"); - - assertThat(response.getHeader(SET_COOKIE)).isEqualTo(("SESSION=123; Path=/; Comment=Test Comment")); - - assertNumCookies(1); - assertThat(response.getCookies()[0]).isInstanceOf(MockCookie.class).satisfies(mockCookie -> { - assertThat(mockCookie.getName()).isEqualTo("SESSION"); - assertThat(mockCookie.getPath()).isEqualTo("/"); - assertThat(mockCookie.getComment()).isEqualTo("Test Comment"); - }); - } - @Test void addCookieHeader() { response.addHeader(SET_COOKIE, "SESSION=123; Path=/; Secure; HttpOnly; SameSite=Lax"); @@ -504,26 +486,6 @@ void addCookieHeader() { assertCookieValues("123", "999"); } - @Test - void addCookieHeaderWithComment() { - response.addHeader(SET_COOKIE, "SESSION=123; Path=/; Secure; HttpOnly; SameSite=Lax"); - assertNumCookies(1); - assertPrimarySessionCookie("123"); - - // Adding a 2nd cookie header should result in 2 cookies. - response.addHeader(SET_COOKIE, "SESSION=999; Comment=Test Comment; Path=/; Secure; HttpOnly; SameSite=Lax"); - assertNumCookies(2); - assertPrimarySessionCookie("123"); - assertThat(response.getCookies()[1]).isInstanceOf(MockCookie.class).satisfies(mockCookie -> { - assertThat(mockCookie.getName()).isEqualTo("SESSION"); - assertThat(mockCookie.getValue()).isEqualTo("999"); - assertThat(mockCookie.getComment()).isEqualTo("Test Comment"); - assertThat(mockCookie.getPath()).isEqualTo("/"); - assertThat(mockCookie.getSecure()).isTrue(); - assertThat(mockCookie.isHttpOnly()).isTrue(); - }); - } - /** * @since 5.1.11 */ @@ -605,6 +567,7 @@ private void assertCookieValues(String... expected) { assertThat(response.getCookies()).extracting(Cookie::getValue).containsExactly(expected); } + @SuppressWarnings("removal") private void assertPrimarySessionCookie(String expectedValue) { Cookie cookie = this.response.getCookie("SESSION"); assertThat(cookie).asInstanceOf(type(MockCookie.class)).satisfies(mockCookie -> { diff --git a/spring-test/src/test/java/org/springframework/mock/web/MockHttpSessionTests.java b/spring-test/src/test/java/org/springframework/mock/web/MockHttpSessionTests.java index 602290d5597a..f3f5ba9218bb 100644 --- a/spring-test/src/test/java/org/springframework/mock/web/MockHttpSessionTests.java +++ b/spring-test/src/test/java/org/springframework/mock/web/MockHttpSessionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 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. @@ -79,20 +79,6 @@ void getAttributeNamesOnInvalidatedSession() { session::getAttributeNames); } - @Test - void getValueOnInvalidatedSession() { - session.invalidate(); - assertThatIllegalStateException().isThrownBy(() -> - session.getValue("foo")); - } - - @Test - void getValueNamesOnInvalidatedSession() { - session.invalidate(); - assertThatIllegalStateException().isThrownBy( - session::getValueNames); - } - @Test void setAttributeOnInvalidatedSession() { session.invalidate(); @@ -100,13 +86,6 @@ void setAttributeOnInvalidatedSession() { session.setAttribute("name", "value")); } - @Test - void putValueOnInvalidatedSession() { - session.invalidate(); - assertThatIllegalStateException().isThrownBy(() -> - session.putValue("name", "value")); - } - @Test void removeAttributeOnInvalidatedSession() { session.invalidate(); @@ -114,13 +93,6 @@ void removeAttributeOnInvalidatedSession() { session.removeAttribute("name")); } - @Test - void removeValueOnInvalidatedSession() { - session.invalidate(); - assertThatIllegalStateException().isThrownBy(() -> - session.removeValue("name")); - } - @Test void isNewOnInvalidatedSession() { session.invalidate(); diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/result/PrintingResultHandlerTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/result/PrintingResultHandlerTests.java index e7ff36a4cf15..7860292b6a3e 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/result/PrintingResultHandlerTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/result/PrintingResultHandlerTests.java @@ -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. @@ -144,17 +144,16 @@ public void printRequestWithEmptySessionMock() throws Exception { } @Test - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") public void printResponse() throws Exception { Cookie enigmaCookie = new Cookie("enigma", "42"); - enigmaCookie.setComment("This is a comment"); enigmaCookie.setHttpOnly(true); enigmaCookie.setMaxAge(1234); enigmaCookie.setDomain(".example.com"); enigmaCookie.setPath("/crumbs"); enigmaCookie.setSecure(true); - this.response.setStatus(400, "error"); + this.response.setStatus(400); this.response.addHeader("header", "headerValue"); this.response.setContentType("text/plain"); this.response.getWriter().print("content"); @@ -197,7 +196,7 @@ public void printResponse() throws Exception { assertThat(cookie1.endsWith("]")).isTrue(); assertThat(cookie2.startsWith("[" + Cookie.class.getSimpleName())).isTrue(); assertThat(cookie2.contains("name = 'enigma', value = '42', " + - "comment = 'This is a comment', domain = '.example.com', maxAge = 1234, " + + "comment = [null], domain = '.example.com', maxAge = 1234, " + "path = '/crumbs', secure = true, version = 0, httpOnly = true")).isTrue(); assertThat(cookie2.endsWith("]")).isTrue(); } diff --git a/spring-web/src/main/java/org/springframework/http/server/reactive/UndertowServerHttpRequest.java b/spring-web/src/main/java/org/springframework/http/server/reactive/UndertowServerHttpRequest.java index 41e9693e04dd..5fae16cfa8f0 100644 --- a/spring-web/src/main/java/org/springframework/http/server/reactive/UndertowServerHttpRequest.java +++ b/spring-web/src/main/java/org/springframework/http/server/reactive/UndertowServerHttpRequest.java @@ -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. @@ -48,6 +48,7 @@ * * @author Marek Hawrylczak * @author Rossen Stoyanchev + * @author Juergen Hoeller * @since 5.0 */ class UndertowServerHttpRequest extends AbstractServerHttpRequest { @@ -82,15 +83,12 @@ public HttpMethod getMethod() { return HttpMethod.valueOf(this.exchange.getRequestMethod().toString()); } - @SuppressWarnings("deprecation") @Override protected MultiValueMap initCookies() { MultiValueMap cookies = new LinkedMultiValueMap<>(); - // getRequestCookies() is deprecated in Undertow 2.2 - for (String name : this.exchange.getRequestCookies().keySet()) { - Cookie cookie = this.exchange.getRequestCookies().get(name); - HttpCookie httpCookie = new HttpCookie(name, cookie.getValue()); - cookies.add(name, httpCookie); + for (Cookie cookie : this.exchange.requestCookies()) { + HttpCookie httpCookie = new HttpCookie(cookie.getName(), cookie.getValue()); + cookies.add(cookie.getName(), httpCookie); } return cookies; } diff --git a/spring-web/src/main/java/org/springframework/http/server/reactive/UndertowServerHttpResponse.java b/spring-web/src/main/java/org/springframework/http/server/reactive/UndertowServerHttpResponse.java index 70a5b9c3211a..6a195245c90a 100644 --- a/spring-web/src/main/java/org/springframework/http/server/reactive/UndertowServerHttpResponse.java +++ b/spring-web/src/main/java/org/springframework/http/server/reactive/UndertowServerHttpResponse.java @@ -47,6 +47,7 @@ * @author Marek Hawrylczak * @author Rossen Stoyanchev * @author Arjen Poutsma + * @author Juergen Hoeller * @since 5.0 */ class UndertowServerHttpResponse extends AbstractListenerServerHttpResponse implements ZeroCopyHttpOutputMessage { @@ -105,7 +106,6 @@ protected void applyStatusCode() { protected void applyHeaders() { } - @SuppressWarnings("deprecation") @Override protected void applyCookies() { for (String name : getCookies().keySet()) { @@ -123,8 +123,7 @@ protected void applyCookies() { cookie.setSecure(httpCookie.isSecure()); cookie.setHttpOnly(httpCookie.isHttpOnly()); cookie.setSameSiteMode(httpCookie.getSameSite()); - // getResponseCookies() is deprecated in Undertow 2.2 - this.exchange.getResponseCookies().putIfAbsent(name, cookie); + this.exchange.setResponseCookie(cookie); } } } @@ -135,14 +134,10 @@ public Mono writeWith(Path file, long position, long count) { Mono.create(sink -> { try { FileChannel source = FileChannel.open(file, StandardOpenOption.READ); - - TransferBodyListener listener = new TransferBodyListener(source, position, - count, sink); + TransferBodyListener listener = new TransferBodyListener(source, position, count, sink); sink.onDispose(listener::closeSource); - StreamSinkChannel destination = this.exchange.getResponseChannel(); destination.getWriteSetter().set(listener::transfer); - listener.transfer(destination); } catch (IOException ex) { diff --git a/spring-web/src/main/java/org/springframework/web/util/ContentCachingResponseWrapper.java b/spring-web/src/main/java/org/springframework/web/util/ContentCachingResponseWrapper.java index ab13b1c88fb1..dd9a46cab6fc 100644 --- a/spring-web/src/main/java/org/springframework/web/util/ContentCachingResponseWrapper.java +++ b/spring-web/src/main/java/org/springframework/web/util/ContentCachingResponseWrapper.java @@ -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. @@ -78,7 +78,6 @@ public void sendError(int sc) throws IOException { } @Override - @SuppressWarnings("deprecation") public void sendError(int sc, String msg) throws IOException { copyBodyToResponse(false); try { @@ -86,7 +85,7 @@ public void sendError(int sc, String msg) throws IOException { } catch (IllegalStateException ex) { // Possibly on Tomcat when called too late: fall back to silent setStatus - super.setStatus(sc, msg); + super.setStatus(sc); } } diff --git a/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockCookie.java b/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockCookie.java index b9736f41559e..23a74b54940f 100644 --- a/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockCookie.java +++ b/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockCookie.java @@ -36,6 +36,7 @@ * @author Sam Brannen * @since 5.1 */ +@SuppressWarnings("removal") public class MockCookie extends Cookie { private static final long serialVersionUID = 4312531139502726325L; diff --git a/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockHttpServletRequest.java b/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockHttpServletRequest.java index 6ccbf589fef0..44174534e426 100644 --- a/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockHttpServletRequest.java +++ b/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockHttpServletRequest.java @@ -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; @@ -79,7 +80,7 @@ * is {@link Locale#ENGLISH}. This value can be changed via {@link #addPreferredLocale} * or {@link #setPreferredLocales}. * - *

As of Spring Framework 5.0, this set of mocks is designed on a Servlet 4.0 baseline. + *

As of Spring 6.0, this set of mocks is designed on a Servlet 6.0 baseline. * * @author Juergen Hoeller * @author Rod Johnson @@ -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; } @@ -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 @@ -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) { @@ -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(); diff --git a/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockHttpServletResponse.java b/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockHttpServletResponse.java index 762bd7a79587..52aab6a61dca 100644 --- a/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockHttpServletResponse.java +++ b/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockHttpServletResponse.java @@ -53,7 +53,7 @@ /** * Mock implementation of the {@link jakarta.servlet.http.HttpServletResponse} interface. * - *

As of Spring Framework 5.0, this set of mocks is designed on a Servlet 4.0 baseline. + *

As of Spring 6.0, this set of mocks is designed on a Servlet 6.0 baseline. * * @author Juergen Hoeller * @author Rod Johnson @@ -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()); @@ -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"); @@ -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; diff --git a/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockHttpSession.java b/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockHttpSession.java index a33c7c9a2236..99742394801b 100644 --- a/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockHttpSession.java +++ b/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockHttpSession.java @@ -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. @@ -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. * - *

As of Spring 5.0, this set of mocks is designed on a Servlet 4.0 baseline. + *

As of Spring 6.0, this set of mocks is designed on a Servlet 6.0 baseline. * * @author Juergen Hoeller * @author Rod Johnson @@ -148,11 +147,6 @@ public int getMaxInactiveInterval() { return this.maxInactiveInterval; } - @Override - public jakarta.servlet.http.HttpSessionContext getSessionContext() { - throw new UnsupportedOperationException("getSessionContext"); - } - @Override public Object getAttribute(String name) { assertIsValid(); @@ -160,23 +154,12 @@ public Object getAttribute(String name) { return this.attributes.get(name); } - @Override - public Object getValue(String name) { - return getAttribute(name); - } - @Override public Enumeration 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(); @@ -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(); @@ -212,11 +190,6 @@ public void removeAttribute(String name) { } } - @Override - public void removeValue(String name) { - removeAttribute(name); - } - /** * Clear all of this session's attributes. */ diff --git a/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockMultipartHttpServletRequest.java b/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockMultipartHttpServletRequest.java index 10a4443fc48f..24d2b464b598 100644 --- a/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockMultipartHttpServletRequest.java +++ b/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockMultipartHttpServletRequest.java @@ -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. @@ -23,6 +23,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Objects; import jakarta.servlet.ServletContext; import jakarta.servlet.ServletException; @@ -42,7 +43,7 @@ * Mock implementation of the * {@link org.springframework.web.multipart.MultipartHttpServletRequest} interface. * - *

As of Spring 5.0, this set of mocks is designed on a Servlet 4.0 baseline. + *

As of Spring 6.0, this set of mocks is designed on a Servlet 6.0 baseline. * *

Useful for testing application controllers that access multipart uploads. * {@link MockMultipartFile} can be used to populate these mock requests with files. @@ -102,12 +103,7 @@ public MultipartFile getFile(String name) { @Override public List getFiles(String name) { List multipartFiles = this.multipartFiles.get(name); - if (multipartFiles != null) { - return multipartFiles; - } - else { - return Collections.emptyList(); - } + return Objects.requireNonNullElse(multipartFiles, Collections.emptyList()); } @Override @@ -142,12 +138,8 @@ public String getMultipartContentType(String paramOrFileName) { @Override public HttpMethod getRequestMethod() { String method = getMethod(); - if (method != null) { - return HttpMethod.valueOf(method); - } - else { - return null; - } + Assert.state(method != null, "Method must not be null"); + return HttpMethod.valueOf(method); } @Override diff --git a/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockServletContext.java b/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockServletContext.java index b44a3b13283f..78f18933064b 100644 --- a/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockServletContext.java +++ b/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockServletContext.java @@ -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. @@ -60,7 +60,7 @@ /** * Mock implementation of the {@link jakarta.servlet.ServletContext} interface. * - *

As of Spring 5.0, this set of mocks is designed on a Servlet 4.0 baseline. + *

As of Spring 6.0, this set of mocks is designed on a Servlet 6.0 baseline. * *

Compatible with Servlet 3.1 but can be configured to expose a specific version * through {@link #setMajorVersion}/{@link #setMinorVersion}; default is 3.1. @@ -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 getServlets() { - return Collections.enumeration(Collections.emptySet()); - } - - @Override - @Deprecated - public Enumeration 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); diff --git a/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockSessionCookieConfig.java b/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockSessionCookieConfig.java index 04f4a8ceabc4..07a76626b25c 100644 --- a/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockSessionCookieConfig.java +++ b/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockSessionCookieConfig.java @@ -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. @@ -16,6 +16,10 @@ package org.springframework.web.testfixture.servlet; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + import jakarta.servlet.SessionCookieConfig; import org.springframework.lang.Nullable; @@ -47,6 +51,8 @@ public class MockSessionCookieConfig implements SessionCookieConfig { private int maxAge = -1; + private Map attributes = new LinkedHashMap<>(); + @Override public void setName(@Nullable String name) { @@ -81,11 +87,13 @@ public String getPath() { return this.path; } + @SuppressWarnings("removal") @Override public void setComment(@Nullable String comment) { this.comment = comment; } + @SuppressWarnings("removal") @Override @Nullable public String getComment() { @@ -122,4 +130,19 @@ public int getMaxAge() { return this.maxAge; } + @Override + public void setAttribute(String name, String value) { + this.attributes.put(name, value); + } + + @Override + public String getAttribute(String name) { + return this.attributes.get(name); + } + + @Override + public Map getAttributes() { + return Collections.unmodifiableMap(this.attributes); + } + } diff --git a/spring-webflux/spring-webflux.gradle b/spring-webflux/spring-webflux.gradle index a8a814863fb3..b7cc4daf2d7c 100644 --- a/spring-webflux/spring-webflux.gradle +++ b/spring-webflux/spring-webflux.gradle @@ -11,6 +11,7 @@ dependencies { optional(project(":spring-context-support")) // for FreeMarker support optional("jakarta.servlet:jakarta.servlet-api") optional("jakarta.websocket:jakarta.websocket-api") + optional("jakarta.websocket:jakarta.websocket-client-api") optional("org.webjars:webjars-locator-core") optional("org.freemarker:freemarker") optional("com.fasterxml.jackson.core:jackson-databind") @@ -25,7 +26,7 @@ dependencies { exclude group: "jakarta.servlet", module: "jakarta.servlet-api" } optional("org.eclipse.jetty.websocket:websocket-jetty-client") - optional("io.undertow:undertow-websockets-jsr-jakarta") + optional("io.undertow:undertow-websockets-jsr") optional("org.jetbrains.kotlin:kotlin-reflect") optional("org.jetbrains.kotlin:kotlin-stdlib") optional("com.google.protobuf:protobuf-java-util") diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultServerRequest.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultServerRequest.java index 12c764c69081..96e0a94e716f 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultServerRequest.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultServerRequest.java @@ -507,12 +507,6 @@ public void setStatus(int sc) { this.status = sc; } - @Override - @Deprecated - public void setStatus(int sc, String sm) { - this.status = sc; - } - @Override public int getStatus() { return this.status; @@ -553,18 +547,6 @@ public String encodeRedirectURL(String url) { throw new UnsupportedOperationException(); } - @Override - @Deprecated - public String encodeUrl(String url) { - throw new UnsupportedOperationException(); - } - - @Override - @Deprecated - public String encodeRedirectUrl(String url) { - throw new UnsupportedOperationException(); - } - @Override public void sendError(int sc, String msg) throws IOException { throw new UnsupportedOperationException(); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/DispatcherServletTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/DispatcherServletTests.java index ad6465cf7afc..595046a04746 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/DispatcherServletTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/DispatcherServletTests.java @@ -98,6 +98,7 @@ public void setup() throws ServletException { complexConfig.addInitParameter("publishContext", "false"); complexConfig.addInitParameter("class", "notWritable"); complexConfig.addInitParameter("unknownParam", "someValue"); + complexConfig.addInitParameter("jakarta.servlet.http.legacyDoHead", "true"); simpleDispatcherServlet = new DispatcherServlet(); simpleDispatcherServlet.setContextClass(SimpleWebApplicationContext.class); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/AbstractServletHandlerMethodTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/AbstractServletHandlerMethodTests.java index 4c260f3a8a35..1f7ec54b519f 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/AbstractServletHandlerMethodTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/AbstractServletHandlerMethodTests.java @@ -110,7 +110,9 @@ protected WebApplicationContext createWebApplicationContext(@Nullable WebApplica } }; - servlet.init(new MockServletConfig()); + MockServletConfig config = new MockServletConfig(); + config.addInitParameter("jakarta.servlet.http.legacyDoHead", "true"); + servlet.init(config); return wac; } diff --git a/spring-websocket/spring-websocket.gradle b/spring-websocket/spring-websocket.gradle index 3c9d011b4a8a..333a9a5c98bc 100644 --- a/spring-websocket/spring-websocket.gradle +++ b/spring-websocket/spring-websocket.gradle @@ -8,6 +8,7 @@ dependencies { optional(project(":spring-webmvc")) optional("jakarta.servlet:jakarta.servlet-api") optional("jakarta.websocket:jakarta.websocket-api") + optional("jakarta.websocket:jakarta.websocket-client-api") optional("org.apache.tomcat:tomcat-websocket") { exclude group: "org.apache.tomcat", module: "tomcat-servlet-api" exclude group: "org.apache.tomcat", module: "tomcat-websocket-api" @@ -21,8 +22,8 @@ dependencies { } optional("org.eclipse.jetty.websocket:websocket-jetty-client") optional("org.eclipse.jetty:jetty-client") - optional("io.undertow:undertow-servlet-jakarta") - optional("io.undertow:undertow-websockets-jsr-jakarta") + optional("io.undertow:undertow-servlet") + optional("io.undertow:undertow-websockets-jsr") optional("com.fasterxml.jackson.core:jackson-databind") testImplementation(testFixtures(project(":spring-core"))) testImplementation(testFixtures(project(":spring-web"))) diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/server/standard/AbstractTyrusRequestUpgradeStrategy.java b/spring-websocket/src/main/java/org/springframework/web/socket/server/standard/AbstractTyrusRequestUpgradeStrategy.java index 3a9f7b0561f5..a02b18b82f7a 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/server/standard/AbstractTyrusRequestUpgradeStrategy.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/server/standard/AbstractTyrusRequestUpgradeStrategy.java @@ -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. @@ -72,7 +72,7 @@ public abstract class AbstractTyrusRequestUpgradeStrategy extends AbstractStanda private static final Constructor constructor; - private static boolean constructorWithBooleanArgument; + private static final boolean constructorWithBooleanArgument; private static final Method registerMethod; diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/server/standard/StandardWebSocketUpgradeStrategy.java b/spring-websocket/src/main/java/org/springframework/web/socket/server/standard/StandardWebSocketUpgradeStrategy.java new file mode 100644 index 000000000000..0ac70abe408c --- /dev/null +++ b/spring-websocket/src/main/java/org/springframework/web/socket/server/standard/StandardWebSocketUpgradeStrategy.java @@ -0,0 +1,77 @@ +/* + * 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. + * 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.web.socket.server.standard; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.websocket.Endpoint; +import jakarta.websocket.Extension; + +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.lang.Nullable; +import org.springframework.web.socket.server.HandshakeFailureException; + +/** + * A WebSocket {@code RequestUpgradeStrategy} for the Jakarta WebSocket API 2.1+. + * + *

To modify properties of the underlying {@link jakarta.websocket.server.ServerContainer} + * you can use {@link ServletServerContainerFactoryBean} in XML configuration or, + * when using Java configuration, access the container instance through the + * "jakarta.websocket.server.ServerContainer" ServletContext attribute. + * + * @author Juergen Hoeller + * @since 6.0 + * @see jakarta.websocket.server.ServerContainer#upgradeHttpToWebSocket + */ +public class StandardWebSocketUpgradeStrategy extends AbstractStandardUpgradeStrategy { + + @Override + public String[] getSupportedVersions() { + return new String[] {"13"}; + } + + @Override + public void upgradeInternal(ServerHttpRequest request, ServerHttpResponse response, + @Nullable String selectedProtocol, List selectedExtensions, Endpoint endpoint) + throws HandshakeFailureException { + + HttpServletRequest servletRequest = getHttpServletRequest(request); + HttpServletResponse servletResponse = getHttpServletResponse(response); + + StringBuffer requestUrl = servletRequest.getRequestURL(); + String path = servletRequest.getRequestURI(); // shouldn't matter + Map pathParams = Collections. emptyMap(); + + ServerEndpointRegistration endpointConfig = new ServerEndpointRegistration(path, endpoint); + endpointConfig.setSubprotocols(Collections.singletonList(selectedProtocol)); + endpointConfig.setExtensions(selectedExtensions); + + try { + getContainer(servletRequest).upgradeHttpToWebSocket(servletRequest, servletResponse, endpointConfig, pathParams); + } + catch (Exception ex) { + throw new HandshakeFailureException( + "Servlet request failed to upgrade to WebSocket: " + requestUrl, ex); + } + } + +} diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/server/standard/TomcatRequestUpgradeStrategy.java b/spring-websocket/src/main/java/org/springframework/web/socket/server/standard/TomcatRequestUpgradeStrategy.java index 20e5f7a435db..2344cf660c38 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/server/standard/TomcatRequestUpgradeStrategy.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/server/standard/TomcatRequestUpgradeStrategy.java @@ -42,6 +42,7 @@ * * @author Rossen Stoyanchev * @since 4.0 + * @see WsServerContainer#upgradeHttpToWebSocket */ public class TomcatRequestUpgradeStrategy extends AbstractStandardUpgradeStrategy { diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/server/support/AbstractHandshakeHandler.java b/spring-websocket/src/main/java/org/springframework/web/socket/server/support/AbstractHandshakeHandler.java index a7a5f4e0d976..ead6f06852e1 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/server/support/AbstractHandshakeHandler.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/server/support/AbstractHandshakeHandler.java @@ -47,6 +47,7 @@ import org.springframework.web.socket.server.HandshakeFailureException; import org.springframework.web.socket.server.HandshakeHandler; import org.springframework.web.socket.server.RequestUpgradeStrategy; +import org.springframework.web.socket.server.standard.StandardWebSocketUpgradeStrategy; /** * A base class for {@link HandshakeHandler} implementations, independent of the Servlet API. @@ -149,7 +150,8 @@ else if (websphereWsPresent) { className = "org.springframework.web.socket.server.standard.WebSphereRequestUpgradeStrategy"; } else { - throw new IllegalStateException("No suitable default RequestUpgradeStrategy found"); + // Let's assume Jakarta WebSocket API 2.1+ + return new StandardWebSocketUpgradeStrategy(); } try {