Merge branch '6.2.x'
This commit is contained in:
commit
b699b65b40
|
@ -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`] and xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-callable[`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,6 +98,47 @@ xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-configuration-spring-mvc[config
|
|||
|
||||
|
||||
|
||||
|
||||
[[mvc-ann-async-webasynctask]]
|
||||
== `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]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
@GetMapping("/callable")
|
||||
WebAsyncTask<String> handle() {
|
||||
return new WebAsyncTask<String>(20000L,()->{
|
||||
Thread.sleep(10000); //simulate long-running task
|
||||
return "asynchronous request completed";
|
||||
});
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
@GetMapping("/callable")
|
||||
fun handle(): WebAsyncTask<String> {
|
||||
return WebAsyncTask(20000L) {
|
||||
Thread.sleep(10000) // simulate long-running task
|
||||
"asynchronous request completed"
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
|
||||
|
||||
[[mvc-ann-async-processing]]
|
||||
== Processing
|
||||
|
||||
|
@ -390,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).
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<TestAnnotation> mergedAnnotation = MergedAnnotations.from(source).get(TestAnnotation.class);
|
||||
|
|
|
@ -984,7 +984,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");
|
||||
|
|
|
@ -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<String, Integer> length = String::length;
|
||||
assertThat(length.andThen(this.moduloTwo).convert("example")).isEqualTo(1);
|
||||
assertThat(length.andThen(this.addOne).convert("example")).isEqualTo(8);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -104,7 +104,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) {
|
||||
|
|
|
@ -104,7 +104,7 @@ class SpringHandlerInstantiatorTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
void applicationContextAwaretypeResolverBuilder() throws JsonProcessingException {
|
||||
void applicationContextAwareTypeResolverBuilder() throws JsonProcessingException {
|
||||
this.objectMapper.writeValueAsString(new Group());
|
||||
assertThat(CustomTypeResolverBuilder.isAutowiredFiledInitialized).isTrue();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue