From 3f0892b42c4c0c7218709fd5da66d2ebd19c6307 Mon Sep 17 00:00:00 2001 From: Tran Ngoc Nhan Date: Sat, 10 May 2025 20:17:33 +0700 Subject: [PATCH 1/5] Fix typos Closes gh-34876 Signed-off-by: Tran Ngoc Nhan --- .../springframework/validation/ValidationUtils.java | 4 ++-- .../annotation/AnnotationBackCompatibilityTests.java | 4 ++-- .../core/annotation/MergedAnnotationsTests.java | 2 +- .../core/convert/converter/ConverterTests.java | 4 ++-- .../org/springframework/util/AntPathMatcherTests.java | 10 +++++----- .../core/BridgeMethodResolverKotlinTests.kt | 4 ++-- .../converter/json/SpringHandlerInstantiatorTests.java | 4 ++-- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/spring-context/src/main/java/org/springframework/validation/ValidationUtils.java b/spring-context/src/main/java/org/springframework/validation/ValidationUtils.java index 042668317d..1d4c227153 100644 --- a/spring-context/src/main/java/org/springframework/validation/ValidationUtils.java +++ b/spring-context/src/main/java/org/springframework/validation/ValidationUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -250,7 +250,7 @@ public abstract class ValidationUtils { Assert.notNull(errors, "Errors object must not be null"); Object value = errors.getFieldValue(field); - if (value == null ||!StringUtils.hasText(value.toString())) { + if (value == null || !StringUtils.hasText(value.toString())) { errors.rejectValue(field, errorCode, errorArgs, defaultMessage); } } diff --git a/spring-core/src/test/java/org/springframework/core/annotation/AnnotationBackCompatibilityTests.java b/spring-core/src/test/java/org/springframework/core/annotation/AnnotationBackCompatibilityTests.java index 9ca47d7f63..434bfe7c93 100644 --- a/spring-core/src/test/java/org/springframework/core/annotation/AnnotationBackCompatibilityTests.java +++ b/spring-core/src/test/java/org/springframework/core/annotation/AnnotationBackCompatibilityTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,7 +32,7 @@ import static org.assertj.core.api.Assertions.assertThat; class AnnotationBackCompatibilityTests { @Test - void multiplRoutesToMetaAnnotation() { + void multipleRoutesToMetaAnnotation() { Class source = WithMetaMetaTestAnnotation1AndMetaTestAnnotation2.class; // Merged annotation chooses lowest depth MergedAnnotation mergedAnnotation = MergedAnnotations.from(source).get(TestAnnotation.class); diff --git a/spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationsTests.java b/spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationsTests.java index 093b570a53..e28a243c37 100644 --- a/spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationsTests.java +++ b/spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationsTests.java @@ -983,7 +983,7 @@ class MergedAnnotationsTests { } @Test - void getDirectFromClassgetDirectFromClassMetaMetaAnnotatedClass() { + void getDirectFromClassGetDirectFromClassMetaMetaAnnotatedClass() { MergedAnnotation annotation = MergedAnnotations.from( MetaMetaAnnotatedClass.class, SearchStrategy.TYPE_HIERARCHY).get(Component.class); assertThat(annotation.getString("value")).isEqualTo("meta2"); diff --git a/spring-core/src/test/java/org/springframework/core/convert/converter/ConverterTests.java b/spring-core/src/test/java/org/springframework/core/convert/converter/ConverterTests.java index 65d519f540..f72f2069cd 100644 --- a/spring-core/src/test/java/org/springframework/core/convert/converter/ConverterTests.java +++ b/spring-core/src/test/java/org/springframework/core/convert/converter/ConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,7 +46,7 @@ class ConverterTests { } @Test - void andThenCanConvertfromDifferentSourceType() { + void andThenCanConvertFromDifferentSourceType() { Converter length = String::length; assertThat(length.andThen(this.moduloTwo).convert("example")).isEqualTo(1); assertThat(length.andThen(this.addOne).convert("example")).isEqualTo(8); diff --git a/spring-core/src/test/java/org/springframework/util/AntPathMatcherTests.java b/spring-core/src/test/java/org/springframework/util/AntPathMatcherTests.java index e1352e5eec..6de3602cbf 100644 --- a/spring-core/src/test/java/org/springframework/util/AntPathMatcherTests.java +++ b/spring-core/src/test/java/org/springframework/util/AntPathMatcherTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -491,8 +491,8 @@ class AntPathMatcherTests { assertThat(comparator.compare("/hotels/{hotel}/bookings/{booking}", "/hotels/{hotel}/booking")).isEqualTo(1); // SPR-10550 - assertThat(comparator.compare("/hotels/{hotel}/bookings/{booking}/cutomers/{customer}", "/**")).isEqualTo(-1); - assertThat(comparator.compare("/**", "/hotels/{hotel}/bookings/{booking}/cutomers/{customer}")).isEqualTo(1); + assertThat(comparator.compare("/hotels/{hotel}/bookings/{booking}/customers/{customer}", "/**")).isEqualTo(-1); + assertThat(comparator.compare("/**", "/hotels/{hotel}/bookings/{booking}/customers/{customer}")).isEqualTo(1); assertThat(comparator.compare("/**", "/**")).isEqualTo(0); assertThat(comparator.compare("/hotels/{hotel}", "/hotels/*")).isEqualTo(-1); @@ -505,8 +505,8 @@ class AntPathMatcherTests { assertThat(comparator.compare("/hotels/{hotel}", "/hotels/{hotel}.*")).isEqualTo(2); // SPR-6741 - assertThat(comparator.compare("/hotels/{hotel}/bookings/{booking}/cutomers/{customer}", "/hotels/**")).isEqualTo(-1); - assertThat(comparator.compare("/hotels/**", "/hotels/{hotel}/bookings/{booking}/cutomers/{customer}")).isEqualTo(1); + assertThat(comparator.compare("/hotels/{hotel}/bookings/{booking}/customers/{customer}", "/hotels/**")).isEqualTo(-1); + assertThat(comparator.compare("/hotels/**", "/hotels/{hotel}/bookings/{booking}/customers/{customer}")).isEqualTo(1); assertThat(comparator.compare("/hotels/foo/bar/**", "/hotels/{hotel}")).isEqualTo(1); assertThat(comparator.compare("/hotels/{hotel}", "/hotels/foo/bar/**")).isEqualTo(-1); diff --git a/spring-core/src/test/kotlin/org/springframework/core/BridgeMethodResolverKotlinTests.kt b/spring-core/src/test/kotlin/org/springframework/core/BridgeMethodResolverKotlinTests.kt index bb94dd3867..f1c8eabc1e 100644 --- a/spring-core/src/test/kotlin/org/springframework/core/BridgeMethodResolverKotlinTests.kt +++ b/spring-core/src/test/kotlin/org/springframework/core/BridgeMethodResolverKotlinTests.kt @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,7 +22,7 @@ import org.junit.jupiter.api.Test /** * Kotlin tests for [BridgeMethodResolver]. * - * @author Sebastien Deleuzes + * @author Sebastien Deleuze */ class BridgeMethodResolverKotlinTests { diff --git a/spring-web/src/test/java/org/springframework/http/converter/json/SpringHandlerInstantiatorTests.java b/spring-web/src/test/java/org/springframework/http/converter/json/SpringHandlerInstantiatorTests.java index 3c9a9b4e5b..a042df3795 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/json/SpringHandlerInstantiatorTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/json/SpringHandlerInstantiatorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -103,7 +103,7 @@ class SpringHandlerInstantiatorTests { } @Test - void applicationContextAwaretypeResolverBuilder() throws JsonProcessingException { + void applicationContextAwareTypeResolverBuilder() throws JsonProcessingException { this.objectMapper.writeValueAsString(new Group()); assertThat(CustomTypeResolverBuilder.isAutowiredFiledInitialized).isTrue(); } From d9459bdc7454d00d9463d4ffce6b2986f6e43863 Mon Sep 17 00:00:00 2001 From: addoDev Date: Tue, 13 May 2025 16:04:53 +0530 Subject: [PATCH 2/5] Improve mvc-ann-async.adoc Added section for WebAsyncTask return type along with java and kotlin example code See gh-34885 Signed-off-by: addoDev --- .../ROOT/pages/web/webmvc/mvc-ann-async.adoc | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/framework-docs/modules/ROOT/pages/web/webmvc/mvc-ann-async.adoc b/framework-docs/modules/ROOT/pages/web/webmvc/mvc-ann-async.adoc index 7c67abdfcf..ec3ae99914 100644 --- a/framework-docs/modules/ROOT/pages/web/webmvc/mvc-ann-async.adoc +++ b/framework-docs/modules/ROOT/pages/web/webmvc/mvc-ann-async.adoc @@ -4,7 +4,7 @@ Spring MVC has an extensive integration with Servlet asynchronous request xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-processing[processing]: -* xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-deferredresult[`DeferredResult`] and xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-callable[`Callable`] +* xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-deferredresult[`DeferredResult`],xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-callable[`Callable`] and xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-webasynctask[`WebAsyncTask`](holder/wrapper for Callable) return values in controller methods provide basic support for a single asynchronous return value. * Controllers can xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-http-streaming[stream] multiple values, including @@ -96,6 +96,42 @@ xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-configuration-spring-mvc[config +[[mvc-ann-async-webasynctask]] +== `WebAsyncTask` + +`WebAsyncTask` is a holder/wrapper for a `java.util.concurrent.Callable` that allows you to set a custom asynchronous request timeout value and a custom `AsyncTaskExecutor` for executing the `java.util.concurrent.Callable` if you want to use a different `AsyncTaskExecutor` than the default one used by Spring MVC. Below is an example of using `WebAsyncTask`: + +[tabs] +====== +Java:: ++ +[source,java,indent=0,subs="verbatim,quotes"] +---- + @GetMapping("/callable") + WebAsyncTask asynchronousRequestProcessingWithCallableWrappedInaWebAsyncTask() { + return new WebAsyncTask(20000L,()->{ + Thread.sleep(10000); //simulate long running task + return "asynchronous request completed"; + }); + } +---- + +Kotlin:: ++ +[source,kotlin,indent=0,subs="verbatim,quotes"] +---- +@GetMapping("/callable") +fun asynchronousRequestProcessingWithCallableWrappedInWebAsyncTask(): WebAsyncTask { + return WebAsyncTask(20000L) { + Thread.sleep(10000) // simulate long-running task + "asynchronous request completed" + } +} +---- +====== + + + [[mvc-ann-async-processing]] == Processing From 06f69915cb165fa069cc037db0a7a323905273c5 Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Tue, 3 Jun 2025 19:04:17 +0100 Subject: [PATCH 3/5] Polishing contribution Closes gh-34885 --- .../ROOT/pages/web/webmvc/mvc-ann-async.adoc | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/framework-docs/modules/ROOT/pages/web/webmvc/mvc-ann-async.adoc b/framework-docs/modules/ROOT/pages/web/webmvc/mvc-ann-async.adoc index ec3ae99914..57f9133c48 100644 --- a/framework-docs/modules/ROOT/pages/web/webmvc/mvc-ann-async.adoc +++ b/framework-docs/modules/ROOT/pages/web/webmvc/mvc-ann-async.adoc @@ -4,11 +4,13 @@ Spring MVC has an extensive integration with Servlet asynchronous request xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-processing[processing]: -* xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-deferredresult[`DeferredResult`],xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-callable[`Callable`] and xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-webasynctask[`WebAsyncTask`](holder/wrapper for Callable) -return values in controller methods provide basic support for a single asynchronous -return value. +* xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-deferredresult[`DeferredResult`], +xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-callable[`Callable`], and +xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-webasynctask[`WebAsyncTask`] return values +in controller methods provide support for a single asynchronous return value. * Controllers can xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-http-streaming[stream] multiple values, including -xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-sse[SSE] and xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-output-stream[raw data]. +xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-sse[SSE] and +xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-output-stream[raw data]. * Controllers can use reactive clients and return xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-reactive-types[reactive types] for response handling. @@ -96,10 +98,14 @@ xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-configuration-spring-mvc[config + [[mvc-ann-async-webasynctask]] == `WebAsyncTask` -`WebAsyncTask` is a holder/wrapper for a `java.util.concurrent.Callable` that allows you to set a custom asynchronous request timeout value and a custom `AsyncTaskExecutor` for executing the `java.util.concurrent.Callable` if you want to use a different `AsyncTaskExecutor` than the default one used by Spring MVC. Below is an example of using `WebAsyncTask`: +`WebAsyncTask` is comparable to using xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-callable[Callable] +but allows customizing additional settings such a request timeout value, and the +`AsyncTaskExecutor` to execute the `java.util.concurrent.Callable` with instead +of the defaults set up globally for Spring MVC. Below is an example of using `WebAsyncTask`: [tabs] ====== @@ -108,9 +114,9 @@ Java:: [source,java,indent=0,subs="verbatim,quotes"] ---- @GetMapping("/callable") - WebAsyncTask asynchronousRequestProcessingWithCallableWrappedInaWebAsyncTask() { + WebAsyncTask handle() { return new WebAsyncTask(20000L,()->{ - Thread.sleep(10000); //simulate long running task + Thread.sleep(10000); //simulate long-running task return "asynchronous request completed"; }); } @@ -121,7 +127,7 @@ Kotlin:: [source,kotlin,indent=0,subs="verbatim,quotes"] ---- @GetMapping("/callable") -fun asynchronousRequestProcessingWithCallableWrappedInWebAsyncTask(): WebAsyncTask { +fun handle(): WebAsyncTask { return WebAsyncTask(20000L) { Thread.sleep(10000) // simulate long-running task "asynchronous request completed" @@ -132,6 +138,7 @@ fun asynchronousRequestProcessingWithCallableWrappedInWebAsyncTask(): WebAsyncTa + [[mvc-ann-async-processing]] == Processing From 31903a9d92c2d2351be00cf79fb92a5d6e71b889 Mon Sep 17 00:00:00 2001 From: DongNyoung Lee <121621378+Dongnyoung@users.noreply.github.com> Date: Tue, 6 May 2025 20:12:36 +0900 Subject: [PATCH 4/5] Fix typo in MockClientHttpRequest Javadoc Closes gh-34856 Signed-off-by: DongNyoung Lee <121621378+Dongnyoung@users.noreply.github.com> --- .../springframework/mock/http/client/MockClientHttpRequest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-test/src/main/java/org/springframework/mock/http/client/MockClientHttpRequest.java b/spring-test/src/main/java/org/springframework/mock/http/client/MockClientHttpRequest.java index 10736fe4f0..90f1c88f7a 100644 --- a/spring-test/src/main/java/org/springframework/mock/http/client/MockClientHttpRequest.java +++ b/spring-test/src/main/java/org/springframework/mock/http/client/MockClientHttpRequest.java @@ -105,7 +105,7 @@ public class MockClientHttpRequest extends MockHttpOutputMessage implements Clie /** * Set the {@link ClientHttpResponse} to be used as the result of executing - * the this request. + * this request. * @see #execute() */ public void setResponse(ClientHttpResponse clientHttpResponse) { From be17315f63224993ba547bc074626d1803d40f59 Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Tue, 3 Jun 2025 19:10:03 +0100 Subject: [PATCH 5/5] Add mention of CompletionStage in "Async Requests" Closes gh-34991 --- framework-docs/modules/ROOT/pages/web/webmvc/mvc-ann-async.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework-docs/modules/ROOT/pages/web/webmvc/mvc-ann-async.adoc b/framework-docs/modules/ROOT/pages/web/webmvc/mvc-ann-async.adoc index 57f9133c48..3f71ba4852 100644 --- a/framework-docs/modules/ROOT/pages/web/webmvc/mvc-ann-async.adoc +++ b/framework-docs/modules/ROOT/pages/web/webmvc/mvc-ann-async.adoc @@ -433,7 +433,7 @@ reactive types from the controller method. Reactive return values are handled as follows: * A single-value promise is adapted to, similar to using `DeferredResult`. Examples -include `Mono` (Reactor) or `Single` (RxJava). +include `CompletionStage` (JDK), Mono` (Reactor), and `Single` (RxJava). * A multi-value stream with a streaming media type (such as `application/x-ndjson` or `text/event-stream`) is adapted to, similar to using `ResponseBodyEmitter` or `SseEmitter`. Examples include `Flux` (Reactor) or `Observable` (RxJava).