Support handler methods returning void, Observable<Void>, etc.

This commit is contained in:
Sebastien Deleuze
2015-11-30 14:13:12 +01:00
parent 57dc8199fb
commit 91c2b7afad
3 changed files with 134 additions and 20 deletions

View File

@@ -16,12 +16,20 @@
package org.springframework.web.reactive.handler;
import java.util.concurrent.CompletableFuture;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.reactivestreams.Publisher;
import reactor.rx.Stream;
import rx.Observable;
import org.springframework.core.ResolvableType;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.core.convert.support.ReactiveStreamsToCompletableFutureConverter;
import org.springframework.core.convert.support.ReactiveStreamsToReactorConverter;
import org.springframework.core.convert.support.ReactiveStreamsToRxJava1Converter;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.reactive.HandlerResult;
@@ -38,7 +46,7 @@ public class SimpleHandlerResultHandlerTests {
HandlerMethod hm = new HandlerMethod(controller, TestController.class.getMethod("voidReturnValue"));
ResolvableType type = ResolvableType.forMethodParameter(hm.getReturnType());
assertFalse(resultHandler.supports(new HandlerResult(hm, null, type)));
assertTrue(resultHandler.supports(new HandlerResult(hm, null, type)));
hm = new HandlerMethod(controller, TestController.class.getMethod("publisherString"));
type = ResolvableType.forMethodParameter(hm.getReturnType());
@@ -47,14 +55,61 @@ public class SimpleHandlerResultHandlerTests {
hm = new HandlerMethod(controller, TestController.class.getMethod("publisherVoid"));
type = ResolvableType.forMethodParameter(hm.getReturnType());
assertTrue(resultHandler.supports(new HandlerResult(hm, null, type)));
hm = new HandlerMethod(controller, TestController.class.getMethod("streamVoid"));
type = ResolvableType.forMethodParameter(hm.getReturnType());
// Reactor Stream is a Publisher
assertTrue(resultHandler.supports(new HandlerResult(hm, null, type)));
hm = new HandlerMethod(controller, TestController.class.getMethod("observableVoid"));
type = ResolvableType.forMethodParameter(hm.getReturnType());
assertFalse(resultHandler.supports(new HandlerResult(hm, null, type)));
hm = new HandlerMethod(controller, TestController.class.getMethod("completableFutureVoid"));
type = ResolvableType.forMethodParameter(hm.getReturnType());
assertFalse(resultHandler.supports(new HandlerResult(hm, null, type)));
}
@Test
public void supportsWithConversionService() throws NoSuchMethodException {
GenericConversionService conversionService = new GenericConversionService();
conversionService.addConverter(new ReactiveStreamsToCompletableFutureConverter());
conversionService.addConverter(new ReactiveStreamsToReactorConverter());
conversionService.addConverter(new ReactiveStreamsToRxJava1Converter());
SimpleHandlerResultHandler resultHandler = new SimpleHandlerResultHandler(conversionService);
TestController controller = new TestController();
HandlerMethod hm = new HandlerMethod(controller, TestController.class.getMethod("voidReturnValue"));
ResolvableType type = ResolvableType.forMethodParameter(hm.getReturnType());
assertTrue(resultHandler.supports(new HandlerResult(hm, null, type)));
hm = new HandlerMethod(controller, TestController.class.getMethod("publisherString"));
type = ResolvableType.forMethodParameter(hm.getReturnType());
assertFalse(resultHandler.supports(new HandlerResult(hm, null, type)));
hm = new HandlerMethod(controller, TestController.class.getMethod("publisherVoid"));
type = ResolvableType.forMethodParameter(hm.getReturnType());
assertTrue(resultHandler.supports(new HandlerResult(hm, null, type)));
hm = new HandlerMethod(controller, TestController.class.getMethod("streamVoid"));
type = ResolvableType.forMethodParameter(hm.getReturnType());
assertTrue(resultHandler.supports(new HandlerResult(hm, null, type)));
hm = new HandlerMethod(controller, TestController.class.getMethod("observableVoid"));
type = ResolvableType.forMethodParameter(hm.getReturnType());
assertTrue(resultHandler.supports(new HandlerResult(hm, null, type)));
hm = new HandlerMethod(controller, TestController.class.getMethod("completableFutureVoid"));
type = ResolvableType.forMethodParameter(hm.getReturnType());
assertTrue(resultHandler.supports(new HandlerResult(hm, null, type)));
}
@SuppressWarnings("unused")
private static class TestController {
public Publisher<String> voidReturnValue() {
return null;
public void voidReturnValue() {
}
public Publisher<String> publisherString() {
@@ -64,6 +119,18 @@ public class SimpleHandlerResultHandlerTests {
public Publisher<Void> publisherVoid() {
return null;
}
public Stream<Void> streamVoid() {
return null;
}
public Observable<Void> observableVoid() {
return null;
}
public CompletableFuture<Void> completableFutureVoid() {
return null;
}
}
}

View File

@@ -197,16 +197,18 @@ public class RequestMappingIntegrationTests extends AbstractHttpHandlerIntegrati
}
@Test
public void create() throws Exception {
RestTemplate restTemplate = new RestTemplate();
URI url = new URI("http://localhost:" + this.port + "/create");
RequestEntity<List<Person>> request = RequestEntity.post(url)
.contentType(MediaType.APPLICATION_JSON)
.body(Arrays.asList(new Person("Robert"), new Person("Marie")));
ResponseEntity<Void> response = restTemplate.exchange(request, Void.class);
public void publisherCreate() throws Exception {
create("http://localhost:" + this.port + "/publisher-create");
}
assertEquals(HttpStatus.OK, response.getStatusCode());
assertEquals(2, this.wac.getBean(TestController.class).persons.size());
@Test
public void streamCreate() throws Exception {
create("http://localhost:" + this.port + "/stream-create");
}
@Test
public void observableCreate() throws Exception {
create("http://localhost:" + this.port + "/observable-create");
}
@@ -259,6 +261,18 @@ public class RequestMappingIntegrationTests extends AbstractHttpHandlerIntegrati
assertEquals("MARIE", results.get(1).getName());
}
private void create(String requestUrl) throws Exception {
RestTemplate restTemplate = new RestTemplate();
URI url = new URI(requestUrl);
RequestEntity<List<Person>> request = RequestEntity.post(url)
.contentType(MediaType.APPLICATION_JSON)
.body(Arrays.asList(new Person("Robert"), new Person("Marie")));
ResponseEntity<Void> response = restTemplate.exchange(request, Void.class);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertEquals(2, this.wac.getBean(TestController.class).persons.size());
}
@Configuration
@SuppressWarnings("unused")
@@ -295,7 +309,7 @@ public class RequestMappingIntegrationTests extends AbstractHttpHandlerIntegrati
@Bean
public SimpleHandlerResultHandler simpleHandlerResultHandler() {
return new SimpleHandlerResultHandler();
return new SimpleHandlerResultHandler(conversionService());
}
}
@@ -448,11 +462,21 @@ public class RequestMappingIntegrationTests extends AbstractHttpHandlerIntegrati
});
}
@RequestMapping("/create")
public Publisher<Void> create(@RequestBody Stream<Person> personStream) {
@RequestMapping("/publisher-create")
public Publisher<Void> publisherCreate(@RequestBody Publisher<Person> personStream) {
return Streams.wrap(personStream).toList().onSuccess(persons::addAll).after();
}
@RequestMapping("/stream-create")
public Promise<Void> streamCreate(@RequestBody Stream<Person> personStream) {
return personStream.toList().onSuccess(persons::addAll).after();
}
@RequestMapping("/observable-create")
public Observable<Void> observableCreate(@RequestBody Observable<Person> personStream) {
return personStream.toList().doOnNext(p -> persons.addAll(p)).flatMap(document -> Observable.empty());
}
//TODO add mixed and T request mappings tests
}