Add bodyToMono/bodyToFlux convenience methods

This commit adds a bodyToMono and bodyToFlux convenience method to
ClientResponse/ServerRequest, similar to the body(Publisher) method that
is on ClientRequest/ServerResponse.
This commit is contained in:
Arjen Poutsma
2016-10-20 16:50:25 +02:00
parent 2a279b7064
commit fa9cc1eb1a
13 changed files with 190 additions and 39 deletions

View File

@@ -23,7 +23,6 @@ import java.time.ZonedDateTime;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Mono;
import org.springframework.core.ResolvableType;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
@@ -318,16 +317,6 @@ public interface ClientRequest<T> {
*/
<T, S extends Publisher<T>> ClientRequest<S> body(S publisher, Class<T> elementClass);
/**
* Set the body of the request to the given {@code Publisher} and return it.
* @param publisher the {@code Publisher} to write to the request
* @param elementType the type of elements contained in the publisher
* @param <T> the type of the elements contained in the publisher
* @param <S> the type of the {@code Publisher}.
* @return the built request
*/
<T, S extends Publisher<T>> ClientRequest<S> body(S publisher, ResolvableType elementType);
}

View File

@@ -20,6 +20,9 @@ import java.util.List;
import java.util.Optional;
import java.util.OptionalLong;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
@@ -55,6 +58,23 @@ public interface ClientResponse {
*/
<T> T body(BodyExtractor<T, ? super ClientHttpResponse> extractor);
/**
* Extract the body to a {@code Mono}.
* @param elementClass the class of element in the {@code Mono}
* @param <T> the element type
* @return the body as a mono
*/
<T> Mono<T> bodyToMono(Class<? extends T> elementClass);
/**
* Extract the body to a {@code Flux}.
* @param elementClass the class of element in the {@code Flux}
* @param <T> the element type
* @return the body as a flux
*/
<T> Flux<T> bodyToFlux(Class<? extends T> elementClass);
/**
* Represents the headers of the HTTP response.
* @see ClientResponse#headers()

View File

@@ -28,7 +28,6 @@ import java.util.stream.Stream;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Mono;
import org.springframework.core.ResolvableType;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
@@ -151,12 +150,6 @@ class DefaultClientRequestBuilder implements ClientRequest.BodyBuilder {
return body(BodyInserters.fromPublisher(publisher, elementClass));
}
@Override
public <T, S extends Publisher<T>> ClientRequest<S> body(S publisher,
ResolvableType elementType) {
return body(BodyInserters.fromPublisher(publisher, elementType));
}
private static class BodyInserterRequest<T> implements ClientRequest<T> {
private final HttpMethod method;

View File

@@ -23,11 +23,15 @@ import java.util.OptionalLong;
import java.util.function.Supplier;
import java.util.stream.Stream;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.reactive.ClientHttpResponse;
import org.springframework.http.codec.BodyExtractor;
import org.springframework.http.codec.BodyExtractors;
import org.springframework.http.codec.HttpMessageReader;
/**
@@ -71,8 +75,14 @@ class DefaultClientResponse implements ClientResponse {
});
}
public ClientHttpResponse clientHttpResponse() {
return this.response;
@Override
public <T> Mono<T> bodyToMono(Class<? extends T> elementClass) {
return body(BodyExtractors.toMono(elementClass));
}
@Override
public <T> Flux<T> bodyToFlux(Class<? extends T> elementClass) {
return body(BodyExtractors.toFlux(elementClass));
}
private class DefaultHeaders implements Headers {

View File

@@ -115,5 +115,46 @@ public class DefaultClientResponseTests {
assertEquals("foo", resultMono.block());
}
@Test
public void bodyToMono() throws Exception {
DefaultDataBufferFactory factory = new DefaultDataBufferFactory();
DefaultDataBuffer dataBuffer =
factory.wrap(ByteBuffer.wrap("foo".getBytes(StandardCharsets.UTF_8)));
Flux<DataBuffer> body = Flux.just(dataBuffer);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.TEXT_PLAIN);
when(mockResponse.getHeaders()).thenReturn(httpHeaders);
when(mockResponse.getBody()).thenReturn(body);
Set<HttpMessageReader<?>> messageReaders = Collections
.singleton(new DecoderHttpMessageReader<String>(new StringDecoder()));
when(mockWebClientStrategies.messageReaders()).thenReturn(messageReaders::stream);
Mono<String> resultMono = defaultClientResponse.bodyToMono(String.class);
assertEquals("foo", resultMono.block());
}
@Test
public void bodyToFlux() throws Exception {
DefaultDataBufferFactory factory = new DefaultDataBufferFactory();
DefaultDataBuffer dataBuffer =
factory.wrap(ByteBuffer.wrap("foo".getBytes(StandardCharsets.UTF_8)));
Flux<DataBuffer> body = Flux.just(dataBuffer);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.TEXT_PLAIN);
when(mockResponse.getHeaders()).thenReturn(httpHeaders);
when(mockResponse.getBody()).thenReturn(body);
Set<HttpMessageReader<?>> messageReaders = Collections
.singleton(new DecoderHttpMessageReader<String>(new StringDecoder()));
when(mockWebClientStrategies.messageReaders()).thenReturn(messageReaders::stream);
Flux<String> resultFlux = defaultClientResponse.bodyToFlux(String.class);
Mono<List<String>> result = resultFlux.collectList();
assertEquals(Collections.singletonList("foo"), result.block());
}
}