diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyExtractors.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyExtractors.java index 2fad402232..cec34ce4b2 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyExtractors.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyExtractors.java @@ -50,13 +50,14 @@ public abstract class BodyExtractors { private static final ResolvableType FORM_MAP_TYPE = ResolvableType.forClassWithGenerics(MultiValueMap.class, String.class, String.class); - private static final ResolvableType MULTIPART_MAP_TYPE = ResolvableType.forClassWithGenerics( - MultiValueMap.class, String.class, Part.class); + private static final ResolvableType MULTIPART_MAP_TYPE = + ResolvableType.forClassWithGenerics(MultiValueMap.class, String.class, Part.class); private static final ResolvableType PART_TYPE = ResolvableType.forClass(Part.class); private static final ResolvableType VOID_TYPE = ResolvableType.forClass(Void.class); + /** * Return a {@code BodyExtractor} that reads into a Reactor {@link Mono}. * @param elementClass the class of element in the {@code Mono} @@ -69,8 +70,9 @@ public abstract class BodyExtractors { /** * Return a {@code BodyExtractor} that reads into a Reactor {@link Mono}. - * The given {@link ParameterizedTypeReference} is used to pass generic type information, for - * instance when using the {@link org.springframework.web.reactive.function.client.WebClient WebClient} + * The given {@link ParameterizedTypeReference} is used to pass generic type + * information, for instance when using the + * {@link org.springframework.web.reactive.function.client.WebClient WebClient}: *
 	 * Mono<Map<String, String>> body = this.webClient
 	 *  .get()
@@ -118,8 +120,9 @@ public abstract class BodyExtractors {
 
 	/**
 	 * Return a {@code BodyExtractor} that reads into a Reactor {@link Flux}.
-	 * The given {@link ParameterizedTypeReference} is used to pass generic type information, for
-	 * instance when using the {@link org.springframework.web.reactive.function.client.WebClient WebClient}
+	 * 

The given {@link ParameterizedTypeReference} is used to pass generic type + * information, for instance when using the + * {@link org.springframework.web.reactive.function.client.WebClient WebClient}: *

 	 * Flux<ServerSentEvent<String>> body = this.webClient
 	 *  .get()
@@ -167,9 +170,7 @@ public abstract class BodyExtractors {
 	 * Return a {@code BodyExtractor} that reads form data into a {@link MultiValueMap}.
 	 * @return a {@code BodyExtractor} that reads form data
 	 */
-	// Note that the returned BodyExtractor is parameterized to ServerHttpRequest, not
-	// ReactiveHttpInputMessage like other methods, since reading form data only typically happens on
-	// the server-side
+	// Parameterized for server-side use
 	public static BodyExtractor>, ServerHttpRequest> toFormData() {
 		return (request, context) -> {
 			ResolvableType type = FORM_MAP_TYPE;
@@ -182,13 +183,11 @@ public abstract class BodyExtractors {
 	}
 
 	/**
-	 * Return a {@code BodyExtractor} that reads multipart (i.e. file upload) form data into a
-	 * {@link MultiValueMap}.
+	 * Return a {@code BodyExtractor} that reads multipart (i.e. file upload) form data
+	 * into a {@link MultiValueMap}.
 	 * @return a {@code BodyExtractor} that reads multipart data
 	 */
-	// Note that the returned BodyExtractor is parameterized to ServerHttpRequest, not
-	// ReactiveHttpInputMessage like other methods, since reading form data only typically happens on
-	// the server-side
+	// Parameterized for server-side use
 	public static BodyExtractor>, ServerHttpRequest> toMultipartData() {
 		return (serverRequest, context) -> {
 			ResolvableType type = MULTIPART_MAP_TYPE;
@@ -201,13 +200,11 @@ public abstract class BodyExtractors {
 	}
 
 	/**
-	 * Return a {@code BodyExtractor} that reads multipart (i.e. file upload) form data into a
-	 * {@link MultiValueMap}.
+	 * Return a {@code BodyExtractor} that reads multipart (i.e. file upload) form data
+	 * into a {@link MultiValueMap}.
 	 * @return a {@code BodyExtractor} that reads multipart data
 	 */
-	// Note that the returned BodyExtractor is parameterized to ServerHttpRequest, not
-	// ReactiveHttpInputMessage like other methods, since reading form data only typically happens on
-	// the server-side
+	// Parameterized for server-side use
 	public static BodyExtractor, ServerHttpRequest> toParts() {
 		return (serverRequest, context) -> {
 			ResolvableType type = PART_TYPE;
@@ -219,10 +216,10 @@ public abstract class BodyExtractors {
 	}
 
 	/**
-	 * Return a {@code BodyExtractor} that returns the body of the message as a {@link Flux} of
-	 * {@link DataBuffer}s.
-	 * 

Note that the returned buffers should be released after usage by calling - * {@link org.springframework.core.io.buffer.DataBufferUtils#release(DataBuffer)} + * Return a {@code BodyExtractor} that returns the body of the message as a {@link Flux} + * of {@link DataBuffer}s. + *

Note that the returned buffers should be released after usage by + * calling {@link org.springframework.core.io.buffer.DataBufferUtils#release(DataBuffer)}. * @return a {@code BodyExtractor} that returns the body * @see ReactiveHttpInputMessage#getBody() */ diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponse.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponse.java index 64647ccdb1..a685242bb6 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponse.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponse.java @@ -102,7 +102,7 @@ class DefaultClientResponse implements ClientResponse { @Override public Mono bodyToMono(Class elementClass) { - if (Void.class.isAssignableFrom(elementClass)) { + if (Void.class == elementClass) { return consumeAndCancel(); } else { @@ -110,6 +110,56 @@ class DefaultClientResponse implements ClientResponse { } } + @Override + public Mono bodyToMono(ParameterizedTypeReference typeReference) { + if (Void.class == typeReference.getType()) { + return consumeAndCancel(); + } + else { + return body(BodyExtractors.toMono(typeReference)); + } + } + + @Override + public Flux bodyToFlux(Class elementClass) { + if (Void.class == elementClass) { + return Flux.from(consumeAndCancel()); + } + else { + return body(BodyExtractors.toFlux(elementClass)); + } + } + + @Override + public Flux bodyToFlux(ParameterizedTypeReference typeReference) { + if (Void.class == typeReference.getType()) { + return Flux.from(consumeAndCancel()); + } + else { + return body(BodyExtractors.toFlux(typeReference)); + } + } + + @Override + public Mono> toEntity(Class bodyType) { + if (Void.class == bodyType) { + return toEntityInternal(consumeAndCancel()); + } + else { + return toEntityInternal(bodyToMono(bodyType)); + } + } + + @Override + public Mono> toEntity(ParameterizedTypeReference typeReference) { + if (Void.class == typeReference.getType()) { + return toEntityInternal(consumeAndCancel()); + } + else { + return toEntityInternal(bodyToMono(typeReference)); + } + } + @SuppressWarnings("unchecked") private Mono consumeAndCancel() { return (Mono) this.response.getBody() @@ -121,56 +171,6 @@ class DefaultClientResponse implements ClientResponse { .then(); } - @Override - public Mono bodyToMono(ParameterizedTypeReference typeReference) { - if (Void.class.isAssignableFrom(typeReference.getType().getClass())) { - return consumeAndCancel(); - } - else { - return body(BodyExtractors.toMono(typeReference)); - } - } - - @Override - public Flux bodyToFlux(Class elementClass) { - if (Void.class.isAssignableFrom(elementClass)) { - return Flux.from(consumeAndCancel()); - } - else { - return body(BodyExtractors.toFlux(elementClass)); - } - } - - @Override - public Flux bodyToFlux(ParameterizedTypeReference typeReference) { - if (Void.class.isAssignableFrom(typeReference.getType().getClass())) { - return Flux.from(consumeAndCancel()); - } - else { - return body(BodyExtractors.toFlux(typeReference)); - } - } - - @Override - public Mono> toEntity(Class bodyType) { - if (Void.class.isAssignableFrom(bodyType)) { - return toEntityInternal(consumeAndCancel()); - } - else { - return toEntityInternal(bodyToMono(bodyType)); - } - } - - @Override - public Mono> toEntity(ParameterizedTypeReference typeReference) { - if (Void.class.isAssignableFrom(typeReference.getType().getClass())) { - return toEntityInternal(consumeAndCancel()); - } - else { - return toEntityInternal(bodyToMono(typeReference)); - } - } - private Mono> toEntityInternal(Mono bodyMono) { HttpHeaders headers = headers().asHttpHeaders(); HttpStatus statusCode = statusCode();