HandlerAdapter is asynchronous again

This commit is contained in:
Rossen Stoyanchev 2015-10-30 15:02:54 -04:00
parent 01ae961820
commit 6b73993a38
6 changed files with 40 additions and 23 deletions

View File

@ -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<HandlerResult> 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;
}
}

View File

@ -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<HandlerResult> handle(ReactiveServerHttpRequest request,
ReactiveServerHttpResponse response, Object handler);
}

View File

@ -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<HandlerResult> handle(ReactiveServerHttpRequest request,
ReactiveServerHttpResponse response, Object handler) {
HttpHandler httpHandler = (HttpHandler)handler;
Publisher<Void> completion = httpHandler.handle(request, response);
return new HandlerResult(httpHandler, completion);
return Publishers.just(new HandlerResult(httpHandler, completion));
}
}

View File

@ -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<HandlerResult> 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);
}
}
}
}

View File

@ -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<Void> request = RequestEntity.get(url).build();
ResponseEntity<byte[]> 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<Void> request = RequestEntity.get(url).build();
ResponseEntity<byte[]> response = restTemplate.exchange(request, byte[].class);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertArrayEquals("bar".getBytes(UTF_8), response.getBody());
}

View File

@ -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());