From e92174c772c0d787be7721ae00c7189f16b05fb5 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Tue, 2 Feb 2016 11:40:49 -0500 Subject: [PATCH] Update HandlerResult Rename result to returnValue and resultType to returnValueType to reflect what they represent. The returnValue getter is also wrapped as Optional since the value returned from a handler may be null (e.g. void method, null value). --- .../web/reactive/DispatcherHandler.java | 2 +- .../web/reactive/HandlerResult.java | 61 +++++++++++++------ .../handler/SimpleHandlerResultHandler.java | 14 +++-- .../annotation/ResponseBodyResultHandler.java | 11 ++-- .../method/InvocableHandlerMethodTests.java | 8 +-- 5 files changed, 62 insertions(+), 34 deletions(-) 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 7b37bf23a75..318f52a991d 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 @@ -146,7 +146,7 @@ public class DispatcherHandler implements WebHandler, ApplicationContextAware { return resultHandler; } } - throw new IllegalStateException("No HandlerResultHandler for " + handlerResult.getResult()); + throw new IllegalStateException("No HandlerResultHandler for " + handlerResult.getReturnValue()); } diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/HandlerResult.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/HandlerResult.java index 9ffae86ba46..69b21f9986b 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/HandlerResult.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/HandlerResult.java @@ -16,6 +16,7 @@ package org.springframework.web.reactive; +import java.util.Optional; import java.util.function.Function; import reactor.core.publisher.Mono; @@ -32,40 +33,54 @@ public class HandlerResult { private final Object handler; - private final Object result; + private final Optional returnValue; - private final ResolvableType resultType; + private final ResolvableType returnValueType; private Function> exceptionHandler; - public HandlerResult(Object handler, Object result, ResolvableType resultType) { + /** + * Create a new {@code HandlerResult}. + * @param handler the handler that handled the request + * @param returnValue the return value from the handler possibly {@code null} + * @param returnValueType the return value type + */ + public HandlerResult(Object handler, Object returnValue, ResolvableType returnValueType) { Assert.notNull(handler, "'handler' is required"); - Assert.notNull(handler, "'resultType' is required"); + Assert.notNull(returnValueType, "'returnValueType' is required"); this.handler = handler; - this.result = result; - this.resultType = resultType; + this.returnValue = Optional.ofNullable(returnValue); + this.returnValueType = returnValueType; } + /** + * Return the handler that handled the request. + */ public Object getHandler() { return this.handler; } - public Object getResult() { - return this.result; - } - - public ResolvableType getResultType() { - return this.resultType; + /** + * Return the value returned from the handler wrapped as {@link Optional}. + */ + public Optional getReturnValue() { + return this.returnValue; } /** - * For an async result, failures may occur later during result handling. - * Use this property to configure an exception handler to be invoked if - * result handling fails. - * - * @param function a function to map the the error to an alternative result. + * Return the type of the value returned from the handler. + */ + public ResolvableType getReturnValueType() { + return this.returnValueType; + } + + /** + * Configure an exception handler that may be used to produce an alternative + * result when result handling fails. Especially for an async return value + * errors may occur after the invocation of the handler. + * @param function the error handler * @return the current instance */ public HandlerResult setExceptionHandler(Function> function) { @@ -73,12 +88,20 @@ public class HandlerResult { return this; } + /** + * Whether there is an exception handler. + */ public boolean hasExceptionHandler() { return (this.exceptionHandler != null); } - public Mono applyExceptionHandler(Throwable ex) { - return (hasExceptionHandler() ? this.exceptionHandler.apply(ex) : Mono.error(ex)); + /** + * Apply the exception handler and return the alternative result. + * @param failure the exception + * @return the new result or the same error if there is no exception handler + */ + public Mono applyExceptionHandler(Throwable failure) { + return (hasExceptionHandler() ? this.exceptionHandler.apply(failure) : Mono.error(failure)); } } 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 ed3c513f8aa..fc46f9d5966 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 @@ -16,6 +16,8 @@ package org.springframework.web.reactive.handler; +import java.util.Optional; + import org.reactivestreams.Publisher; import reactor.core.publisher.Mono; @@ -61,7 +63,7 @@ public class SimpleHandlerResultHandler implements Ordered, HandlerResultHandler @Override public boolean supports(HandlerResult result) { - ResolvableType type = result.getResultType(); + ResolvableType type = result.getReturnValueType(); return (type != null && Void.TYPE.equals(type.getRawClass()) || (isConvertibleToPublisher(type) && Void.class.isAssignableFrom(type.getGeneric(0).getRawClass()))); } @@ -75,12 +77,14 @@ public class SimpleHandlerResultHandler implements Ordered, HandlerResultHandler @SuppressWarnings("unchecked") @Override public Mono handleResult(ServerWebExchange exchange, HandlerResult result) { - Object value = result.getResult(); - if (Void.TYPE.equals(result.getResultType().getRawClass())) { + Optional value = result.getReturnValue(); + if (!value.isPresent() || Void.TYPE.equals(result.getReturnValueType().getRawClass())) { return Mono.empty(); } - return (value instanceof Mono ? (Mono)value : - Mono.from(this.conversionService.convert(value, Publisher.class))); + if (value.get() instanceof Mono) { + return (Mono) value.get(); + } + return Mono.from(this.conversionService.convert(value.get(), Publisher.class)); } } diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/method/annotation/ResponseBodyResultHandler.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/method/annotation/ResponseBodyResultHandler.java index da7d4a01cc3..a27b5ce82f0 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/method/annotation/ResponseBodyResultHandler.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/method/annotation/ResponseBodyResultHandler.java @@ -23,6 +23,7 @@ import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -132,23 +133,23 @@ public class ResponseBodyResultHandler implements HandlerResultHandler, Ordered @SuppressWarnings("unchecked") public Mono handleResult(ServerWebExchange exchange, HandlerResult result) { - Object value = result.getResult(); - if (value == null) { + Optional value = result.getReturnValue(); + if (!value.isPresent()) { return Mono.empty(); } Publisher publisher; ResolvableType elementType; - ResolvableType returnType = result.getResultType(); + ResolvableType returnType = result.getReturnValueType(); if (this.conversionService.canConvert(returnType.getRawClass(), Publisher.class)) { - publisher = this.conversionService.convert(value, Publisher.class); + publisher = this.conversionService.convert(value.get(), Publisher.class); elementType = returnType.getGeneric(0); if (Void.class.equals(elementType.getRawClass())) { return (Mono)Mono.from(publisher); } } else { - publisher = Mono.just(value); + publisher = Mono.just(value.get()); elementType = returnType; } diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/method/InvocableHandlerMethodTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/method/InvocableHandlerMethodTests.java index 892d554e2ad..25273edf2f2 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/method/InvocableHandlerMethodTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/method/InvocableHandlerMethodTests.java @@ -71,7 +71,7 @@ public class InvocableHandlerMethodTests { List values = Stream.from(publisher).toList().get(); assertEquals(1, values.size()); - assertEquals("success", values.get(0).getResult()); + assertEquals("success", values.get(0).getReturnValue().get()); } @Test @@ -84,7 +84,7 @@ public class InvocableHandlerMethodTests { List values = Stream.from(publisher).toList().get(); assertEquals(1, values.size()); - assertEquals("success:null", values.get(0).getResult()); + assertEquals("success:null", values.get(0).getReturnValue().get()); } @Test @@ -96,7 +96,7 @@ public class InvocableHandlerMethodTests { List values = Stream.from(publisher).toList().get(); assertEquals(1, values.size()); - assertEquals("success:value1", values.get(0).getResult()); + assertEquals("success:value1", values.get(0).getReturnValue().get()); } @Test @@ -108,7 +108,7 @@ public class InvocableHandlerMethodTests { List values = Stream.from(publisher).toList().get(); assertEquals(1, values.size()); - assertEquals("success:value1", values.get(0).getResult()); + assertEquals("success:value1", values.get(0).getReturnValue().get()); } @Test