Add support for ResponseEntity result handling

This commit is contained in:
Rossen Stoyanchev
2016-06-21 17:27:52 -04:00
parent 59b7c25003
commit 9aa6f5caac
8 changed files with 455 additions and 85 deletions

View File

@@ -55,6 +55,7 @@ import org.springframework.web.reactive.accept.RequestedContentTypeResolver;
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.reactive.result.method.annotation.ResponseBodyResultHandler;
import org.springframework.web.reactive.result.method.annotation.ResponseEntityResultHandler;
import org.springframework.web.reactive.result.view.HttpMessageConverterView;
import org.springframework.web.reactive.result.view.View;
import org.springframework.web.reactive.result.view.ViewResolutionResultHandler;
@@ -183,13 +184,12 @@ public class WebReactiveConfigurationTests {
service.canConvert(Observable.class, Flux.class);
}
@Test
public void responseBodyResultHandler() throws Exception {
public void responseEntityResultHandler() throws Exception {
ApplicationContext context = loadConfig(WebReactiveConfiguration.class);
String name = "responseBodyResultHandler";
ResponseBodyResultHandler handler = context.getBean(name, ResponseBodyResultHandler.class);
String name = "responseEntityResultHandler";
ResponseEntityResultHandler handler = context.getBean(name, ResponseEntityResultHandler.class);
assertNotNull(handler);
assertEquals(0, handler.getOrder());
@@ -202,6 +202,34 @@ public class WebReactiveConfigurationTests {
assertHasConverter(converters, Resource.class, MediaType.IMAGE_PNG);
assertHasConverter(converters, TestBean.class, MediaType.APPLICATION_XML);
assertHasConverter(converters, TestBean.class, MediaType.APPLICATION_JSON);
name = "mvcContentTypeResolver";
RequestedContentTypeResolver resolver = context.getBean(name, RequestedContentTypeResolver.class);
assertSame(resolver, handler.getContentTypeResolver());
}
@Test
public void responseBodyResultHandler() throws Exception {
ApplicationContext context = loadConfig(WebReactiveConfiguration.class);
String name = "responseBodyResultHandler";
ResponseBodyResultHandler handler = context.getBean(name, ResponseBodyResultHandler.class);
assertNotNull(handler);
assertEquals(100, handler.getOrder());
List<HttpMessageConverter<?>> converters = handler.getMessageConverters();
assertEquals(5, converters.size());
assertHasConverter(converters, ByteBuffer.class, MediaType.APPLICATION_OCTET_STREAM);
assertHasConverter(converters, String.class, MediaType.TEXT_PLAIN);
assertHasConverter(converters, Resource.class, MediaType.IMAGE_PNG);
assertHasConverter(converters, TestBean.class, MediaType.APPLICATION_XML);
assertHasConverter(converters, TestBean.class, MediaType.APPLICATION_JSON);
name = "mvcContentTypeResolver";
RequestedContentTypeResolver resolver = context.getBean(name, RequestedContentTypeResolver.class);
assertSame(resolver, handler.getContentTypeResolver());
}
@Test

View File

@@ -172,6 +172,12 @@ public class RequestMappingIntegrationTests extends AbstractHttpHandlerIntegrati
serializeAsPojo("http://localhost:" + port + "/completable-future");
}
@Test
@Ignore // Issue #119
public void serializeAsMonoResponseEntity() throws Exception {
serializeAsPojo("http://localhost:" + port + "/monoResponseEntity");
}
@Test
public void serializeAsMono() throws Exception {
serializeAsPojo("http://localhost:" + port + "/mono");
@@ -450,6 +456,12 @@ public class RequestMappingIntegrationTests extends AbstractHttpHandlerIntegrati
return Observable.just(ByteBuffer.wrap("Hello!".getBytes()));
}
@RequestMapping("/monoResponseEntity")
public ResponseEntity<Mono<Person>> monoResponseEntity() {
Mono<Person> body = Mono.just(new Person("Robert"));
return ResponseEntity.ok(body);
}
@RequestMapping("/mono")
public Mono<Person> monoResponseBody() {
return Mono.just(new Person("Robert"));

View File

@@ -56,6 +56,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.springframework.http.MediaType.APPLICATION_JSON_UTF8;
/**
@@ -87,20 +88,19 @@ public class ResponseBodyResultHandlerTests {
@Test
public void defaultOrder() throws Exception {
ResponseBodyResultHandler handler = createHandler(new StringEncoder());
assertEquals(0, handler.getOrder());
assertEquals(100, handler.getOrder());
}
@Test
public void usesContentTypeResolver() throws Exception {
MediaType contentType = MediaType.APPLICATION_JSON_UTF8;
RequestedContentTypeResolver resolver = new FixedContentTypeResolver(contentType);
RequestedContentTypeResolver resolver = new FixedContentTypeResolver(APPLICATION_JSON_UTF8);
HandlerResultHandler handler = createHandler(resolver, new StringEncoder(), new JacksonJsonEncoder());
ServerWebExchange exchange = createExchange("/foo");
HandlerResult result = new HandlerResult(new Object(), "fooValue", ResolvableType.forClass(String.class));
handler.handleResult(exchange, result).block();
assertEquals(contentType, exchange.getResponse().getHeaders().getContentType());
assertEquals(APPLICATION_JSON_UTF8, exchange.getResponse().getHeaders().getContentType());
}
@Test

View File

@@ -0,0 +1,150 @@
/*
* Copyright 2002-2016 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.reactive.result.method.annotation;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.Test;
import reactor.core.test.TestSubscriber;
import org.springframework.core.ResolvableType;
import org.springframework.core.codec.Encoder;
import org.springframework.core.codec.support.JacksonJsonEncoder;
import org.springframework.core.codec.support.StringEncoder;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.io.buffer.support.DataBufferTestUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.reactive.CodecHttpMessageConverter;
import org.springframework.http.converter.reactive.HttpMessageConverter;
import org.springframework.http.server.reactive.MockServerHttpRequest;
import org.springframework.http.server.reactive.MockServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.ui.ExtendedModelMap;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.reactive.HandlerResult;
import org.springframework.web.reactive.HandlerResultHandler;
import org.springframework.web.reactive.accept.FixedContentTypeResolver;
import org.springframework.web.reactive.accept.HeaderContentTypeResolver;
import org.springframework.web.reactive.accept.RequestedContentTypeResolver;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.adapter.DefaultServerWebExchange;
import org.springframework.web.server.session.WebSessionManager;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.springframework.http.MediaType.APPLICATION_JSON_UTF8;
/**
* Unit tests for {@link ResponseEntityResultHandler}.
* @author Rossen Stoyanchev
*/
public class ResponseEntityResultHandlerTests {
private MockServerHttpResponse response = new MockServerHttpResponse();
@Test
public void supports() throws NoSuchMethodException {
ResponseEntityResultHandler handler = createHandler(new StringEncoder());
TestController controller = new TestController();
HandlerMethod hm = new HandlerMethod(controller, TestController.class.getMethod("responseString"));
ResolvableType type = ResolvableType.forMethodParameter(hm.getReturnType());
assertTrue(handler.supports(new HandlerResult(hm, null, type, new ExtendedModelMap())));
hm = new HandlerMethod(controller, TestController.class.getMethod("responseVoid"));
type = ResolvableType.forMethodParameter(hm.getReturnType());
assertTrue(handler.supports(new HandlerResult(hm, null, type, new ExtendedModelMap())));
hm = new HandlerMethod(controller, TestController.class.getMethod("string"));
type = ResolvableType.forMethodParameter(hm.getReturnType());
assertFalse(handler.supports(new HandlerResult(hm, null, type, new ExtendedModelMap())));
}
@Test
public void defaultOrder() throws Exception {
ResponseEntityResultHandler handler = createHandler(new StringEncoder());
assertEquals(0, handler.getOrder());
}
@Test
public void jsonResponseBody() throws Exception {
RequestedContentTypeResolver resolver = new FixedContentTypeResolver(APPLICATION_JSON_UTF8);
HandlerResultHandler handler = createHandler(resolver, new StringEncoder(), new JacksonJsonEncoder());
TestController controller = new TestController();
HandlerMethod hm = new HandlerMethod(controller, controller.getClass().getMethod("responseString"));
ResolvableType type = ResolvableType.forMethodParameter(hm.getReturnType());
HandlerResult result = new HandlerResult(hm, ResponseEntity.ok("fooValue"), type);
ServerWebExchange exchange = createExchange("/foo");
handler.handleResult(exchange, result).block();
assertEquals(HttpStatus.OK, this.response.getStatus());
assertEquals(APPLICATION_JSON_UTF8, this.response.getHeaders().getContentType());
TestSubscriber.subscribe(this.response.getBody())
.assertValuesWith(buf -> assertEquals("\"fooValue\"",
DataBufferTestUtils.dumpString(buf, Charset.forName("UTF-8"))));
}
private ResponseEntityResultHandler createHandler(Encoder<?>... encoders) {
return createHandler(new HeaderContentTypeResolver(), encoders);
}
private ResponseEntityResultHandler createHandler(RequestedContentTypeResolver resolver,
Encoder<?>... encoders) {
List<HttpMessageConverter<?>> converters = Arrays.stream(encoders)
.map(encoder -> new CodecHttpMessageConverter<>(encoder, null))
.collect(Collectors.toList());
return new ResponseEntityResultHandler(converters, new DefaultConversionService(), resolver);
}
private ServerWebExchange createExchange(String path) throws URISyntaxException {
ServerHttpRequest request = new MockServerHttpRequest(HttpMethod.GET, new URI(path));
WebSessionManager sessionManager = mock(WebSessionManager.class);
return new DefaultServerWebExchange(request, this.response, sessionManager);
}
@SuppressWarnings("unused")
private static class TestController {
public ResponseEntity<String> responseString() {
return null;
}
public ResponseEntity<Void> responseVoid() {
return null;
}
public String string() {
return null;
}
}
}