Add body(Object) method to ServerResponse.BodyBuilder
This method introduces a new body(Object) to ServerResponse, a shortcut to body(BodyInserters.fromObject(Object)). Note that in the implementation of the method, an `instanceof` check is performed to make sure that the passed argument is not a `Publisher`, as users should call `body(Publisher, Class)` for sending a reactive type. This Publisher-check is also done in the `WebClient`, for the same reasons. Issue: SPR-15461
This commit is contained in:
parent
b897f96e0f
commit
30f61e0c07
|
|
@ -35,6 +35,7 @@ import org.springframework.http.HttpMethod;
|
|||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.client.reactive.ClientHttpRequest;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
|
@ -258,19 +259,22 @@ class DefaultWebClient implements WebClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T> RequestHeadersSpec<?> body(BodyInserter<T, ? super ClientHttpRequest> inserter) {
|
||||
public RequestHeadersSpec<?> body(BodyInserter<?, ? super ClientHttpRequest> inserter) {
|
||||
this.inserter = inserter;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, S extends Publisher<T>> RequestHeadersSpec<?> body(S publisher, Class<T> elementClass) {
|
||||
public <T, P extends Publisher<T>> RequestHeadersSpec<?> body(P publisher, Class<T> elementClass) {
|
||||
this.inserter = BodyInserters.fromPublisher(publisher, elementClass);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> RequestHeadersSpec<?> body(T body) {
|
||||
public RequestHeadersSpec<?> body(Object body) {
|
||||
Assert.isTrue(!(body instanceof Publisher), "Please specify the element class by " +
|
||||
"using body(Publisher, Class)");
|
||||
|
||||
this.inserter = BodyInserters.fromObject(body);
|
||||
return this;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -445,10 +445,9 @@ public interface WebClient {
|
|||
/**
|
||||
* Set the body of the request to the given {@code BodyInserter}.
|
||||
* @param inserter the {@code BodyInserter} that writes to the request
|
||||
* @param <T> the type contained in the body
|
||||
* @return this builder
|
||||
*/
|
||||
<T> RequestHeadersSpec<?> body(BodyInserter<T, ? super ClientHttpRequest> inserter);
|
||||
RequestHeadersSpec<?> body(BodyInserter<?, ? super ClientHttpRequest> inserter);
|
||||
|
||||
/**
|
||||
* Set the body of the request to the given {@code Publisher}.
|
||||
|
|
@ -458,10 +457,10 @@ public interface WebClient {
|
|||
* @param publisher the {@code Publisher} to write to the request
|
||||
* @param elementClass the class 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}
|
||||
* @param <P> the type of the {@code Publisher}
|
||||
* @return this builder
|
||||
*/
|
||||
<T, S extends Publisher<T>> RequestHeadersSpec<?> body(S publisher, Class<T> elementClass);
|
||||
<T, P extends Publisher<T>> RequestHeadersSpec<?> body(P publisher, Class<T> elementClass);
|
||||
|
||||
/**
|
||||
* Set the body of the request to the given {@code Object}.
|
||||
|
|
@ -469,10 +468,9 @@ public interface WebClient {
|
|||
* {@linkplain org.springframework.web.reactive.function.BodyInserters#fromObject
|
||||
* Object body inserter}.
|
||||
* @param body the {@code Object} to write to the request
|
||||
* @param <T> the type contained in the body
|
||||
* @return this builder
|
||||
*/
|
||||
<T> RequestHeadersSpec<?> body(T body);
|
||||
RequestHeadersSpec<?> body(Object body);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -189,7 +189,21 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T> Mono<ServerResponse> body(BodyInserter<T, ? super ServerHttpResponse> inserter) {
|
||||
public Mono<ServerResponse> body(Object body) {
|
||||
Assert.notNull(body, "'body' must not be null");
|
||||
Assert.isTrue(!(body instanceof Publisher), "Please specify the element class by using " +
|
||||
"body(Publisher, Class)");
|
||||
|
||||
return new DefaultEntityResponseBuilder<>(body,
|
||||
BodyInserters.fromObject(body))
|
||||
.headers(this.headers)
|
||||
.status(this.statusCode)
|
||||
.build()
|
||||
.map(entityResponse -> entityResponse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<ServerResponse> body(BodyInserter<?, ? super ServerHttpResponse> inserter) {
|
||||
Assert.notNull(inserter, "'inserter' must not be null");
|
||||
return Mono.just(new BodyInserterServerResponse<>(this.statusCode, this.headers, inserter, this.hints));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -341,17 +341,27 @@ public interface ServerResponse {
|
|||
* @param elementClass the class of elements contained in the publisher
|
||||
* @param <T> the type of the elements contained in the publisher
|
||||
* @param <P> the type of the {@code Publisher}
|
||||
* @return the built request
|
||||
* @return the built response
|
||||
*/
|
||||
<T, P extends Publisher<T>> Mono<ServerResponse> body(P publisher, Class<T> elementClass);
|
||||
|
||||
/**
|
||||
* Set the body of the response to the given {@code Object} and return it.
|
||||
* This convenience method combines {@link #body(BodyInserter)} and
|
||||
* {@link BodyInserters#fromObject(Object)}.
|
||||
* @param body the body of the response
|
||||
* @return the built response
|
||||
* @throws IllegalArgumentException if {@code body} is a {@link Publisher}, for which
|
||||
* {@link #body(Publisher, Class)} should be used.
|
||||
*/
|
||||
Mono<ServerResponse> body(Object body);
|
||||
|
||||
/**
|
||||
* Set the body of the response to the given {@code BodyInserter} and return it.
|
||||
* @param inserter the {@code BodyInserter} that writes to the response
|
||||
* @param <T> the type contained in the body
|
||||
* @return the built response
|
||||
*/
|
||||
<T> Mono<ServerResponse> body(BodyInserter<T, ? super ServerHttpResponse> inserter);
|
||||
Mono<ServerResponse> body(BodyInserter<?, ? super ServerHttpResponse> inserter);
|
||||
|
||||
/**
|
||||
* Render the template with the given {@code name} using the given {@code modelAttributes}.
|
||||
|
|
|
|||
|
|
@ -116,6 +116,14 @@ public class DefaultWebClientTests {
|
|||
verifyNoMoreInteractions(this.exchangeFunction);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void bodyObjectPublisher() throws Exception {
|
||||
Mono<Void> mono = Mono.empty();
|
||||
WebClient client = builder().build();
|
||||
|
||||
client.post().uri("http://example.com").body(mono);
|
||||
}
|
||||
|
||||
|
||||
private WebClient.Builder builder() {
|
||||
return WebClient.builder().baseUrl("/base").exchangeFunction(this.exchangeFunction);
|
||||
|
|
|
|||
|
|
@ -35,9 +35,8 @@ import org.springframework.http.MediaType;
|
|||
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
|
|
@ -295,4 +294,12 @@ public class DefaultServerResponseBuilderTests {
|
|||
StepVerifier.create(response.getBody()).expectComplete().verify();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void bodyObjectPublisher() throws Exception {
|
||||
Mono<Void> mono = Mono.empty();
|
||||
|
||||
ServerResponse.ok().body(mono);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -25,7 +25,6 @@ import org.springframework.http.ResponseEntity;
|
|||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.web.reactive.function.BodyInserters.fromObject;
|
||||
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
|
||||
import static org.springframework.web.reactive.function.server.RequestPredicates.path;
|
||||
import static org.springframework.web.reactive.function.server.RouterFunctions.nest;
|
||||
|
|
@ -82,11 +81,11 @@ public class NestedRouteIntegrationTests extends AbstractRouterFunctionIntegrati
|
|||
private static class NestedHandler {
|
||||
|
||||
public Mono<ServerResponse> bar(ServerRequest request) {
|
||||
return ServerResponse.ok().body(fromObject("bar"));
|
||||
return ServerResponse.ok().body("bar");
|
||||
}
|
||||
|
||||
public Mono<ServerResponse> baz(ServerRequest request) {
|
||||
return ServerResponse.ok().body(fromObject("baz"));
|
||||
return ServerResponse.ok().body("baz");
|
||||
}
|
||||
|
||||
public Mono<ServerResponse> variables(ServerRequest request) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue