From 9a1492e4010bc322c2fb00174e13da79d1c95da3 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Thu, 7 Jan 2016 17:09:49 -0500 Subject: [PATCH] Polish --- .../reactive/ErrorHandlingHttpHandler.java | 16 ++-- .../server/reactive/HttpExceptionHandler.java | 2 +- .../http/server/reactive/HttpFilter.java | 2 +- .../http/server/reactive/HttpFilterChain.java | 2 +- .../http/server/reactive/HttpHandler.java | 2 +- .../web/reactive/DispatcherHandler.java | 15 ++-- .../web/reactive/HandlerAdapter.java | 2 +- .../web/reactive/HandlerMapping.java | 3 +- .../web/reactive/HandlerResultHandler.java | 13 +-- .../reactive/handler/HttpHandlerAdapter.java | 4 +- .../handler/SimpleHandlerResultHandler.java | 3 +- .../method/HandlerMethodArgumentResolver.java | 10 +-- .../method/InvocableHandlerMethod.java | 83 +++++++++---------- .../RequestBodyArgumentResolver.java | 8 +- .../RequestMappingHandlerAdapter.java | 16 ++-- 15 files changed, 81 insertions(+), 100 deletions(-) diff --git a/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/ErrorHandlingHttpHandler.java b/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/ErrorHandlingHttpHandler.java index 92e2fa2c9df..09cf6a64137 100644 --- a/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/ErrorHandlingHttpHandler.java +++ b/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/ErrorHandlingHttpHandler.java @@ -44,23 +44,23 @@ public class ErrorHandlingHttpHandler extends HttpHandlerDecorator { @Override public Mono handle(ServerHttpRequest request, ServerHttpResponse response) { - Mono publisher; + Mono mono; try { - publisher = getDelegate().handle(request, response); + mono = getDelegate().handle(request, response); } catch (Throwable ex) { - publisher = Mono.error(ex); + mono = Mono.error(ex); } for (HttpExceptionHandler handler : this.exceptionHandlers) { - publisher = applyExceptionHandler(publisher, handler, request, response); + mono = applyExceptionHandler(mono, handler, request, response); } - return publisher; + return mono; } - private static Mono applyExceptionHandler(Mono publisher, - HttpExceptionHandler handler, ServerHttpRequest request, ServerHttpResponse response) { + private static Mono applyExceptionHandler(Mono mono, HttpExceptionHandler handler, + ServerHttpRequest request, ServerHttpResponse response) { - return publisher.flux().onErrorResumeWith(ex -> handler.handle(request, response, ex)).after(); + return mono.otherwise(ex -> handler.handle(request, response, ex)).after(); } } diff --git a/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/HttpExceptionHandler.java b/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/HttpExceptionHandler.java index 5258d025646..d982c115a79 100644 --- a/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/HttpExceptionHandler.java +++ b/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/HttpExceptionHandler.java @@ -36,7 +36,7 @@ public interface HttpExceptionHandler { * @param request the current request * @param response the current response * @param ex the exception to handle - * @return Publisher to indicate when exception handling is complete. + * @return {@code Mono} to indicate when exception handling is complete. */ Mono handle(ServerHttpRequest request, ServerHttpResponse response, Throwable ex); diff --git a/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/HttpFilter.java b/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/HttpFilter.java index b53fb8639b0..b21b1c2b0fa 100644 --- a/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/HttpFilter.java +++ b/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/HttpFilter.java @@ -39,7 +39,7 @@ public interface HttpFilter { * @param request current HTTP request. * @param response current HTTP response. * @param chain provides a way to delegate to the next HttpFilter. - * @return Publisher to indicate when request processing is complete. + * @return {@code Mono} to indicate when request processing is complete. */ Mono filter(ServerHttpRequest request, ServerHttpResponse response, HttpFilterChain chain); diff --git a/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/HttpFilterChain.java b/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/HttpFilterChain.java index 7650014cadb..0bb70708bc4 100644 --- a/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/HttpFilterChain.java +++ b/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/HttpFilterChain.java @@ -29,7 +29,7 @@ public interface HttpFilterChain { * * @param request current HTTP request. * @param response current HTTP response. - * @return Publisher to indicate when request handling is complete. + * @return {@code Mono} to indicate when request handling is complete. */ Mono filter(ServerHttpRequest request, ServerHttpResponse response); diff --git a/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/HttpHandler.java b/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/HttpHandler.java index 3d90ca52894..328cd891859 100644 --- a/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/HttpHandler.java +++ b/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/HttpHandler.java @@ -33,7 +33,7 @@ public interface HttpHandler { * * @param request current HTTP request. * @param response current HTTP response. - * @return Publisher to indicate when request handling is complete. + * @return {@code Mono} to indicate when request handling is complete. */ Mono handle(ServerHttpRequest request, ServerHttpResponse response); diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/DispatcherHandler.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/DispatcherHandler.java index 93e1aa30317..8b5c676d95b 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/DispatcherHandler.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/DispatcherHandler.java @@ -121,14 +121,13 @@ public class DispatcherHandler implements HttpHandler, ApplicationContextAware { .next() .then(handler -> getHandlerAdapter(handler).handle(request, response, handler)) .then(result -> { - Mono publisher = (result.hasError() ? Mono.error(result.getError()) : - getResultHandler(result).handleResult(request, response, result)); + Mono mono = (result.hasError() ? Mono.error(result.getError()) : + handleResult(request, response, result)); if (result.hasExceptionMapper()) { - return publisher - .otherwise(ex -> result.getExceptionMapper().apply(ex) - .then(errorResult -> getResultHandler(errorResult).handleResult(request, response, errorResult))); + return mono.otherwise(ex -> result.getExceptionMapper().apply(ex) + .then(exResult -> handleResult(request, response, exResult))); } - return publisher; + return mono; }) .otherwise(ex -> Mono.error(this.errorMapper.apply(ex))); } @@ -142,6 +141,10 @@ public class DispatcherHandler implements HttpHandler, ApplicationContextAware { throw new IllegalStateException("No HandlerAdapter: " + handler); } + protected Mono handleResult(ServerHttpRequest request, ServerHttpResponse response, HandlerResult result) { + return getResultHandler(result).handleResult(request, response, result); + } + protected HandlerResultHandler getResultHandler(HandlerResult handlerResult) { for (HandlerResultHandler resultHandler : resultHandlers) { if (resultHandler.supports(handlerResult)) { diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/HandlerAdapter.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/HandlerAdapter.java index c6f5c3541c3..b66676d5378 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/HandlerAdapter.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/HandlerAdapter.java @@ -53,7 +53,7 @@ public interface HandlerAdapter { * @param handler handler to use. This object must have previously been passed * to the {@code supports} method of this interface, which must have * returned {@code true}. - * @return A {@link Publisher} object that produces a single {@link HandlerResult} element + * @return A {@link Mono} that emits a single {@link HandlerResult} element */ Mono handle(ServerHttpRequest request, ServerHttpResponse response, Object handler); diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/HandlerMapping.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/HandlerMapping.java index ae276d62300..b8a164421a9 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/HandlerMapping.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/HandlerMapping.java @@ -32,7 +32,8 @@ public interface HandlerMapping { /** * Return a handler for this request. * @param request current HTTP request - * @return A {@link Mono} object that produces a single handler element + * @return A {@link Mono} that emits one value or none in case the request + * cannot be resolved to a handler. */ Mono getHandler(ServerHttpRequest request); diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/HandlerResultHandler.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/HandlerResultHandler.java index e121bdff985..fe55814ac3c 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/HandlerResultHandler.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/HandlerResultHandler.java @@ -30,8 +30,7 @@ import org.springframework.http.server.reactive.ServerHttpResponse; public interface HandlerResultHandler { /** - * Given a handler instance, return whether or not this {@code HandlerResultHandler} - * can support it. + * Whether this handler supports the given {@link HandlerResult}. * * @param result result object to check * @return whether or not this object can use the given result @@ -39,14 +38,10 @@ public interface HandlerResultHandler { boolean supports(HandlerResult result); /** - * Process the given result in an asynchronous non blocking way, by eventually modifying - * response headers, or writing some data stream into the response. - * Implementations should not throw exceptions but signal them via the returned - * {@code Mono}. + * Process the given result modifying response headers and/or writing data + * to the response. * - * @return A {@code Mono} used to signal the demand, and receive a notification - * when the handling is complete (success or error) including the flush of the data on the - * network. + * @return {@code Mono} to indicate when request handling is complete. */ Mono handleResult(ServerHttpRequest request, ServerHttpResponse response, HandlerResult result); diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/HttpHandlerAdapter.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/HttpHandlerAdapter.java index 853f522f754..13694ce1d7e 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/HttpHandlerAdapter.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/HttpHandlerAdapter.java @@ -50,9 +50,7 @@ public class HttpHandlerAdapter implements HandlerAdapter { } @Override - public Mono handle(ServerHttpRequest request, - ServerHttpResponse response, Object handler) { - + public Mono handle(ServerHttpRequest request, ServerHttpResponse response, Object handler) { HttpHandler httpHandler = (HttpHandler)handler; Mono completion = httpHandler.handle(request, response); return Mono.just(new HandlerResult(httpHandler, completion, PUBLISHER_VOID)); diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/SimpleHandlerResultHandler.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/SimpleHandlerResultHandler.java index 0e27adc704b..ba03013652d 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/SimpleHandlerResultHandler.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/SimpleHandlerResultHandler.java @@ -69,7 +69,8 @@ public class SimpleHandlerResultHandler implements Ordered, HandlerResultHandler private boolean isConvertibleToPublisher(ResolvableType type) { return Publisher.class.isAssignableFrom(type.getRawClass()) || - ((this.conversionService != null) && this.conversionService.canConvert(type.getRawClass(), Publisher.class)); + ((this.conversionService != null) && + this.conversionService.canConvert(type.getRawClass(), Publisher.class)); } @SuppressWarnings("unchecked") diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/method/HandlerMethodArgumentResolver.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/method/HandlerMethodArgumentResolver.java index f7c9c6e1902..b4e7fd68e7f 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/method/HandlerMethodArgumentResolver.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/method/HandlerMethodArgumentResolver.java @@ -31,13 +31,9 @@ public interface HandlerMethodArgumentResolver { boolean supportsParameter(MethodParameter parameter); /** - * The returned Publisher is expected to produce a single value -- i.e. the - * value to use to invoke the handler method. Any additional values will be - * ignored. - * - *

The publisher may also produce zero values if the argument does not - * resolve to any value which will result in passing {@code null} as the - * argument value. + * The returned {@link Mono} may produce one or zero values if the argument + * does not resolve to any value, which will result in {@code null} passed + * as the argument value. */ Mono resolveArgument(MethodParameter parameter, ServerHttpRequest request); diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/method/InvocableHandlerMethod.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/method/InvocableHandlerMethod.java index 116036fd67f..0aaa7a67579 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/method/InvocableHandlerMethod.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/method/InvocableHandlerMethod.java @@ -25,9 +25,7 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; -import reactor.Flux; import reactor.Mono; -import reactor.fn.tuple.Tuple; import org.springframework.core.DefaultParameterNameDiscoverer; import org.springframework.core.GenericTypeResolver; @@ -46,7 +44,7 @@ import org.springframework.web.reactive.HandlerResult; */ public class InvocableHandlerMethod extends HandlerMethod { - public static final Mono NO_ARGS = Mono.just(new Object[0]); + private static final Mono NO_ARGS = Mono.just(new Object[0]); private final static Object NO_VALUE = new Object(); @@ -85,19 +83,7 @@ public class InvocableHandlerMethod extends HandlerMethod { * never throws an exception. */ public Mono invokeForRequest(ServerHttpRequest request, Object... providedArgs) { - - Mono argsPublisher = NO_ARGS; - try { - if (!ObjectUtils.isEmpty(getMethodParameters())) { - List> publishers = resolveArguments(request, providedArgs); - argsPublisher = Flux.zip(publishers, this::initArgs).next(); - } - } - catch (Throwable ex) { - return Mono.error(ex); - } - - return Flux.from(argsPublisher).concatMap(args -> { + return resolveArguments(request, providedArgs).then(args -> { try { Object value = doInvoke(args); ResolvableType type = ResolvableType.forMethodParameter(getReturnType()); @@ -111,35 +97,46 @@ public class InvocableHandlerMethod extends HandlerMethod { String s = getInvocationErrorMessage(args); return Mono.error(new IllegalStateException(s)); } - }).next(); + }); } - private List> resolveArguments(ServerHttpRequest request, Object... providedArgs) { - return Stream.of(getMethodParameters()) - .map(parameter -> { - parameter.initParameterNameDiscovery(this.parameterNameDiscoverer); - GenericTypeResolver.resolveParameterType(parameter, getBean().getClass()); - if (!ObjectUtils.isEmpty(providedArgs)) { - for (Object providedArg : providedArgs) { - if (parameter.getParameterType().isInstance(providedArg)) { - return Mono.just(providedArg); + private Mono resolveArguments(ServerHttpRequest request, Object... providedArgs) { + if (ObjectUtils.isEmpty(getMethodParameters())) { + return NO_ARGS; + } + try { + List> monos = Stream.of(getMethodParameters()) + .map(param -> { + param.initParameterNameDiscovery(this.parameterNameDiscoverer); + GenericTypeResolver.resolveParameterType(param, getBean().getClass()); + if (!ObjectUtils.isEmpty(providedArgs)) { + for (Object providedArg : providedArgs) { + if (param.getParameterType().isInstance(providedArg)) { + return Mono.just(providedArg); + } } } - } - HandlerMethodArgumentResolver resolver = this.resolvers.stream() - .filter(r -> r.supportsParameter(parameter)) - .findFirst() - .orElseThrow(() -> getArgError("No resolver for ", parameter, null)); - try { - return resolver.resolveArgument(parameter, request) - .defaultIfEmpty(NO_VALUE) - .otherwise(ex -> Mono.error(getArgError("Error resolving ", parameter, ex))); - } - catch (Exception ex) { - throw getArgError("Error resolving ", parameter, ex); - } - }) - .collect(Collectors.toList()); + HandlerMethodArgumentResolver resolver = this.resolvers.stream() + .filter(r -> r.supportsParameter(param)) + .findFirst() + .orElseThrow(() -> getArgError("No resolver for ", param, null)); + try { + return resolver.resolveArgument(param, request) + .defaultIfEmpty(NO_VALUE) + .otherwise(ex -> Mono.error(getArgError("Error resolving ", param, ex))); + } + catch (Exception ex) { + throw getArgError("Error resolving ", param, ex); + } + }) + .collect(Collectors.toList()); + + return Mono.when(monos).map(args -> + Stream.of(args.toArray()).map(o -> o != NO_VALUE ? o : null).toArray()); + } + catch (Throwable ex) { + return Mono.error(ex); + } } private IllegalStateException getArgError(String message, MethodParameter param, Throwable cause) { @@ -173,8 +170,4 @@ public class InvocableHandlerMethod extends HandlerMethod { "on method [" + getBridgedMethod().toGenericString() + "]"; } - private Object[] initArgs(Tuple tuple) { - return Stream.of(tuple.toArray()).map(o -> o != NO_VALUE ? o : null).toArray(); - } - } diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/method/annotation/RequestBodyArgumentResolver.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/method/annotation/RequestBodyArgumentResolver.java index 2bb4cdafa17..9302e333a69 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/method/annotation/RequestBodyArgumentResolver.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/method/annotation/RequestBodyArgumentResolver.java @@ -65,19 +65,19 @@ public class RequestBodyArgumentResolver implements HandlerMethodArgumentResolve } ResolvableType type = ResolvableType.forMethodParameter(parameter); Flux body = request.getBody(); - Flux elementStream = body; + Flux elementFlux = body; ResolvableType elementType = type.hasGenerics() ? type.getGeneric(0) : type; Decoder decoder = resolveDecoder(elementType, mediaType); if (decoder != null) { - elementStream = decoder.decode(body, elementType, mediaType); + elementFlux = decoder.decode(body, elementType, mediaType); } if (this.conversionService.canConvert(Publisher.class, type.getRawClass())) { - return Mono.just(this.conversionService.convert(elementStream, type.getRawClass())); + return Mono.just(this.conversionService.convert(elementFlux, type.getRawClass())); } - return (Mono)Mono.from(elementStream); + return elementFlux.next().map(o -> o); } private Decoder resolveDecoder(ResolvableType type, MediaType mediaType, Object... hints) { diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/method/annotation/RequestMappingHandlerAdapter.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/method/annotation/RequestMappingHandlerAdapter.java index d1409e4e939..a6e67927a4d 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/method/annotation/RequestMappingHandlerAdapter.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/method/annotation/RequestMappingHandlerAdapter.java @@ -25,7 +25,6 @@ import java.util.concurrent.ConcurrentHashMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import reactor.Flux; import reactor.Mono; import org.springframework.beans.factory.InitializingBean; @@ -106,23 +105,18 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, Initializin } @Override - public Mono handle(ServerHttpRequest request, - ServerHttpResponse response, Object handler) { + public Mono handle(ServerHttpRequest request, ServerHttpResponse response, + Object handler) { HandlerMethod handlerMethod = (HandlerMethod) handler; InvocableHandlerMethod invocable = new InvocableHandlerMethod(handlerMethod); invocable.setHandlerMethodArgumentResolvers(this.argumentResolvers); - Flux publisher = invocable.invokeForRequest(request).flux(); - publisher = publisher.onErrorResumeWith(ex -> Mono.just(new HandlerResult(handler, ex))); - - - publisher = publisher.map( - result -> result.setExceptionMapper( + return invocable.invokeForRequest(request) + .otherwise(ex -> Mono.just(new HandlerResult(handler, ex))) + .map(result -> result.setExceptionMapper( ex -> mapException(ex, handlerMethod, request, response))); - - return publisher.next(); } private Mono mapException(Throwable ex, HandlerMethod handlerMethod,