From 6b73993a389147bf5010d73c68eacccf11ca9cb5 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Fri, 30 Oct 2015 15:02:54 -0400 Subject: [PATCH] HandlerAdapter is asynchronous again --- .../web/dispatch/DispatcherHandler.java | 19 +++++++-------- .../reactive/web/dispatch/HandlerAdapter.java | 5 +++- .../dispatch/handler/HttpHandlerAdapter.java | 7 ++++-- .../RequestMappingHandlerAdapter.java | 24 ++++++++++++------- ...mpleUrlHandlerMappingIntegrationTests.java | 4 ++++ .../RequestMappingHandlerMappingTests.java | 4 ++-- 6 files changed, 40 insertions(+), 23 deletions(-) diff --git a/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/DispatcherHandler.java b/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/DispatcherHandler.java index 89c372946e..c134df5171 100644 --- a/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/DispatcherHandler.java +++ b/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/DispatcherHandler.java @@ -108,21 +108,21 @@ public class DispatcherHandler implements HttpHandler, ApplicationContextAware { } HandlerAdapter handlerAdapter = getHandlerAdapter(handler); + if (handlerAdapter == null) { + return Publishers.error(new IllegalStateException("No HandlerAdapter for " + handler)); + } - try { - HandlerResult result = handlerAdapter.handle(request, response, handler); + Publisher resultPublisher = handlerAdapter.handle(request, response, handler); + + return Publishers.concatMap(resultPublisher, result -> { for (HandlerResultHandler resultHandler : resultHandlers) { if (resultHandler.supports(result)) { return resultHandler.handleResult(request, response, result); } } return Publishers.error(new IllegalStateException( - "No HandlerResultHandler for " + result.getValue())); - } - catch(Exception ex) { - return Publishers.error(ex); - } - + "No HandlerResultHandler for " + result.getValue())); + }); } protected Object getHandler(ReactiveServerHttpRequest request) { @@ -142,8 +142,7 @@ public class DispatcherHandler implements HttpHandler, ApplicationContextAware { return handlerAdapter; } } - // more specific exception - throw new IllegalStateException("No HandlerAdapter for " + handler); + return null; } } diff --git a/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/HandlerAdapter.java b/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/HandlerAdapter.java index 91d9420412..131a79b826 100644 --- a/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/HandlerAdapter.java +++ b/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/HandlerAdapter.java @@ -16,6 +16,8 @@ package org.springframework.reactive.web.dispatch; +import org.reactivestreams.Publisher; + import org.springframework.http.server.ReactiveServerHttpRequest; import org.springframework.http.server.ReactiveServerHttpResponse; @@ -53,6 +55,7 @@ public interface HandlerAdapter { * @throws Exception in case of errors * @return An {@link HandlerResult} instance */ - HandlerResult handle(ReactiveServerHttpRequest request, ReactiveServerHttpResponse response, Object handler) throws Exception; + Publisher handle(ReactiveServerHttpRequest request, + ReactiveServerHttpResponse response, Object handler); } diff --git a/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/handler/HttpHandlerAdapter.java b/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/handler/HttpHandlerAdapter.java index 67c563355a..2204cd85fe 100644 --- a/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/handler/HttpHandlerAdapter.java +++ b/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/handler/HttpHandlerAdapter.java @@ -17,6 +17,7 @@ package org.springframework.reactive.web.dispatch.handler; import org.reactivestreams.Publisher; +import reactor.Publishers; import org.springframework.http.server.ReactiveServerHttpRequest; import org.springframework.http.server.ReactiveServerHttpResponse; @@ -44,10 +45,12 @@ public class HttpHandlerAdapter implements HandlerAdapter { } @Override - public HandlerResult handle(ReactiveServerHttpRequest request, ReactiveServerHttpResponse response, Object handler) { + public Publisher handle(ReactiveServerHttpRequest request, + ReactiveServerHttpResponse response, Object handler) { + HttpHandler httpHandler = (HttpHandler)handler; Publisher completion = httpHandler.handle(request, response); - return new HandlerResult(httpHandler, completion); + return Publishers.just(new HandlerResult(httpHandler, completion)); } } diff --git a/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/method/annotation/RequestMappingHandlerAdapter.java b/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/method/annotation/RequestMappingHandlerAdapter.java index ad2bfef86e..e4b1f98579 100644 --- a/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/method/annotation/RequestMappingHandlerAdapter.java +++ b/spring-web-reactive/src/main/java/org/springframework/reactive/web/dispatch/method/annotation/RequestMappingHandlerAdapter.java @@ -21,6 +21,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import org.reactivestreams.Publisher; +import reactor.Publishers; + import org.springframework.beans.factory.InitializingBean; import org.springframework.http.server.ReactiveServerHttpRequest; import org.springframework.http.server.ReactiveServerHttpResponse; @@ -70,15 +73,20 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, Initializin } @Override - public HandlerResult handle(ReactiveServerHttpRequest request, ReactiveServerHttpResponse response, - Object handler) throws Exception { + public Publisher handle(ReactiveServerHttpRequest request, + ReactiveServerHttpResponse response, Object handler) { - final InvocableHandlerMethod invocable = new InvocableHandlerMethod((HandlerMethod) handler); - invocable.setHandlerMethodArgumentResolvers(this.argumentResolvers); + InvocableHandlerMethod handlerMethod = new InvocableHandlerMethod((HandlerMethod) handler); + handlerMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers); - Object result = invocable.invokeForRequest(request); - - return new HandlerResult(invocable, result); + try { + Object result = handlerMethod.invokeForRequest(request); + return Publishers.just(new HandlerResult(handlerMethod, result)); + } + catch (Exception e) { + // TODO: remove throws declaration from InvocableHandlerMethod + return Publishers.error(e); + } } -} +} \ No newline at end of file diff --git a/spring-web-reactive/src/test/java/org/springframework/reactive/web/dispatch/handler/SimpleUrlHandlerMappingIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/reactive/web/dispatch/handler/SimpleUrlHandlerMappingIntegrationTests.java index 70ca1c7b5c..34353f8bd4 100644 --- a/spring-web-reactive/src/test/java/org/springframework/reactive/web/dispatch/handler/SimpleUrlHandlerMappingIntegrationTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/reactive/web/dispatch/handler/SimpleUrlHandlerMappingIntegrationTests.java @@ -26,6 +26,7 @@ import org.reactivestreams.Publisher; import reactor.io.buffer.Buffer; import reactor.rx.Streams; +import org.springframework.http.HttpStatus; import org.springframework.http.RequestEntity; import org.springframework.http.ResponseEntity; import org.springframework.http.server.ReactiveServerHttpRequest; @@ -38,6 +39,7 @@ import org.springframework.web.client.RestTemplate; import org.springframework.web.context.support.StaticWebApplicationContext; import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; /** @@ -71,6 +73,7 @@ public class SimpleUrlHandlerMappingIntegrationTests extends AbstractHttpHandler RequestEntity request = RequestEntity.get(url).build(); ResponseEntity response = restTemplate.exchange(request, byte[].class); + assertEquals(HttpStatus.OK, response.getStatusCode()); assertArrayEquals("foo".getBytes(UTF_8), response.getBody()); } @@ -83,6 +86,7 @@ public class SimpleUrlHandlerMappingIntegrationTests extends AbstractHttpHandler RequestEntity request = RequestEntity.get(url).build(); ResponseEntity response = restTemplate.exchange(request, byte[].class); + assertEquals(HttpStatus.OK, response.getStatusCode()); assertArrayEquals("bar".getBytes(UTF_8), response.getBody()); } diff --git a/spring-web-reactive/src/test/java/org/springframework/reactive/web/dispatch/method/annotation/RequestMappingHandlerMappingTests.java b/spring-web-reactive/src/test/java/org/springframework/reactive/web/dispatch/method/annotation/RequestMappingHandlerMappingTests.java index 0d53aac9bf..9ff435f2b6 100644 --- a/spring-web-reactive/src/test/java/org/springframework/reactive/web/dispatch/method/annotation/RequestMappingHandlerMappingTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/reactive/web/dispatch/method/annotation/RequestMappingHandlerMappingTests.java @@ -52,14 +52,14 @@ public class RequestMappingHandlerMappingTests { } @Test - public void path() throws NoSuchMethodException { + public void path() throws Exception { ReactiveServerHttpRequest request = new MockServerHttpRequest(HttpMethod.GET, "boo"); HandlerMethod handler = (HandlerMethod) this.mapping.getHandler(request); assertEquals(TestController.class.getMethod("boo"), handler.getMethod()); } @Test - public void method() throws NoSuchMethodException { + public void method() throws Exception { ReactiveServerHttpRequest request = new MockServerHttpRequest(HttpMethod.POST, "foo"); HandlerMethod handler = (HandlerMethod) this.mapping.getHandler(request); assertEquals(TestController.class.getMethod("postFoo"), handler.getMethod());