Browse Source

Consistent check for Void.class in DefaultClientResponse

Issue: SPR-16636
pull/2028/head
Juergen Hoeller 7 years ago
parent
commit
e28a995ab7
  1. 43
      spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyExtractors.java
  2. 34
      spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponse.java

43
spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyExtractors.java

@ -50,13 +50,14 @@ public abstract class BodyExtractors { @@ -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 { @@ -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}:
* <pre class="code">
* Mono&lt;Map&lt;String, String&gt;&gt; body = this.webClient
* .get()
@ -118,8 +120,9 @@ public abstract class BodyExtractors { @@ -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}
* <p>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}:
* <pre class="code">
* Flux&lt;ServerSentEvent&lt;String&gt;&gt; body = this.webClient
* .get()
@ -167,9 +170,7 @@ public abstract class BodyExtractors { @@ -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<Mono<MultiValueMap<String, String>>, ServerHttpRequest> toFormData() {
return (request, context) -> {
ResolvableType type = FORM_MAP_TYPE;
@ -182,13 +183,11 @@ public abstract class BodyExtractors { @@ -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<Mono<MultiValueMap<String, Part>>, ServerHttpRequest> toMultipartData() {
return (serverRequest, context) -> {
ResolvableType type = MULTIPART_MAP_TYPE;
@ -201,13 +200,11 @@ public abstract class BodyExtractors { @@ -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<Flux<Part>, ServerHttpRequest> toParts() {
return (serverRequest, context) -> {
ResolvableType type = PART_TYPE;
@ -219,10 +216,10 @@ public abstract class BodyExtractors { @@ -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.
* <p><strong>Note</strong> 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.
* <p><strong>Note</strong> 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()
*/

34
spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponse.java

@ -102,7 +102,7 @@ class DefaultClientResponse implements ClientResponse { @@ -102,7 +102,7 @@ class DefaultClientResponse implements ClientResponse {
@Override
public <T> Mono<T> bodyToMono(Class<? extends T> elementClass) {
if (Void.class.isAssignableFrom(elementClass)) {
if (Void.class == elementClass) {
return consumeAndCancel();
}
else {
@ -110,20 +110,9 @@ class DefaultClientResponse implements ClientResponse { @@ -110,20 +110,9 @@ class DefaultClientResponse implements ClientResponse {
}
}
@SuppressWarnings("unchecked")
private <T> Mono<T> consumeAndCancel() {
return (Mono<T>) this.response.getBody()
.map(buffer -> {
DataBufferUtils.release(buffer);
throw new ReadCancellationException();
})
.onErrorResume(ReadCancellationException.class, ex -> Mono.empty())
.then();
}
@Override
public <T> Mono<T> bodyToMono(ParameterizedTypeReference<T> typeReference) {
if (Void.class.isAssignableFrom(typeReference.getType().getClass())) {
if (Void.class == typeReference.getType()) {
return consumeAndCancel();
}
else {
@ -133,7 +122,7 @@ class DefaultClientResponse implements ClientResponse { @@ -133,7 +122,7 @@ class DefaultClientResponse implements ClientResponse {
@Override
public <T> Flux<T> bodyToFlux(Class<? extends T> elementClass) {
if (Void.class.isAssignableFrom(elementClass)) {
if (Void.class == elementClass) {
return Flux.from(consumeAndCancel());
}
else {
@ -143,7 +132,7 @@ class DefaultClientResponse implements ClientResponse { @@ -143,7 +132,7 @@ class DefaultClientResponse implements ClientResponse {
@Override
public <T> Flux<T> bodyToFlux(ParameterizedTypeReference<T> typeReference) {
if (Void.class.isAssignableFrom(typeReference.getType().getClass())) {
if (Void.class == typeReference.getType()) {
return Flux.from(consumeAndCancel());
}
else {
@ -153,7 +142,7 @@ class DefaultClientResponse implements ClientResponse { @@ -153,7 +142,7 @@ class DefaultClientResponse implements ClientResponse {
@Override
public <T> Mono<ResponseEntity<T>> toEntity(Class<T> bodyType) {
if (Void.class.isAssignableFrom(bodyType)) {
if (Void.class == bodyType) {
return toEntityInternal(consumeAndCancel());
}
else {
@ -163,7 +152,7 @@ class DefaultClientResponse implements ClientResponse { @@ -163,7 +152,7 @@ class DefaultClientResponse implements ClientResponse {
@Override
public <T> Mono<ResponseEntity<T>> toEntity(ParameterizedTypeReference<T> typeReference) {
if (Void.class.isAssignableFrom(typeReference.getType().getClass())) {
if (Void.class == typeReference.getType()) {
return toEntityInternal(consumeAndCancel());
}
else {
@ -171,6 +160,17 @@ class DefaultClientResponse implements ClientResponse { @@ -171,6 +160,17 @@ class DefaultClientResponse implements ClientResponse {
}
}
@SuppressWarnings("unchecked")
private <T> Mono<T> consumeAndCancel() {
return (Mono<T>) this.response.getBody()
.map(buffer -> {
DataBufferUtils.release(buffer);
throw new ReadCancellationException();
})
.onErrorResume(ReadCancellationException.class, ex -> Mono.empty())
.then();
}
private <T> Mono<ResponseEntity<T>> toEntityInternal(Mono<T> bodyMono) {
HttpHeaders headers = headers().asHttpHeaders();
HttpStatus statusCode = statusCode();

Loading…
Cancel
Save