diff --git a/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2CodecSupport.java b/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2CodecSupport.java index 11ba5cdf346..6096b5abcc3 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2CodecSupport.java +++ b/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2CodecSupport.java @@ -23,7 +23,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Optional; import com.fasterxml.jackson.annotation.JsonView; import com.fasterxml.jackson.databind.JavaType; @@ -91,19 +90,21 @@ public abstract class Jackson2CodecSupport { } protected Map getHints(ResolvableType resolvableType) { - return getParameter(resolvableType) - .flatMap(parameter -> Optional.ofNullable(getAnnotation(parameter, JsonView.class)) - .map(annotation -> { - Class[] classes = annotation.value(); - Assert.isTrue(classes.length == 1, JSON_VIEW_HINT_ERROR + parameter); - return Collections.singletonMap(JSON_VIEW_HINT, classes[0]); - })) - .orElse(Collections.emptyMap()); + MethodParameter param = getParameter(resolvableType); + if (param != null) { + JsonView annotation = getAnnotation(param, JsonView.class); + if (annotation != null) { + Class[] classes = annotation.value(); + Assert.isTrue(classes.length == 1, JSON_VIEW_HINT_ERROR + param); + return Collections.singletonMap(JSON_VIEW_HINT, classes[0]); + } + } + return Collections.emptyMap(); } - protected Optional getParameter(ResolvableType type) { - return Optional.ofNullable(type.getSource() instanceof MethodParameter ? - (MethodParameter) type.getSource() : null); + @Nullable + protected MethodParameter getParameter(ResolvableType type) { + return type.getSource() instanceof MethodParameter ? (MethodParameter) type.getSource() : null; } @Nullable diff --git a/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonDecoder.java b/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonDecoder.java index 63e0cf85eff..cb746825441 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonDecoder.java +++ b/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonDecoder.java @@ -109,7 +109,8 @@ public class Jackson2JsonDecoder extends Jackson2CodecSupport implements HttpMes Assert.notNull(tokens, "'tokens' must not be null"); Assert.notNull(elementType, "'elementType' must not be null"); - Class contextClass = getParameter(elementType).map(MethodParameter::getContainingClass).orElse(null); + MethodParameter param = getParameter(elementType); + Class contextClass = (param != null ? param.getContainingClass() : null); JavaType javaType = getJavaType(elementType.getType(), contextClass); Class jsonView = (hints != null ? (Class) hints.get(Jackson2CodecSupport.JSON_VIEW_HINT) : null); diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/SyncHandlerMethodArgumentResolver.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/SyncHandlerMethodArgumentResolver.java index bc0392127fb..88c650d737f 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/SyncHandlerMethodArgumentResolver.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/SyncHandlerMethodArgumentResolver.java @@ -21,6 +21,7 @@ import java.util.Optional; import reactor.core.publisher.Mono; import org.springframework.core.MethodParameter; +import org.springframework.lang.Nullable; import org.springframework.web.reactive.BindingContext; import org.springframework.web.server.ServerWebExchange; @@ -50,9 +51,10 @@ public interface SyncHandlerMethodArgumentResolver extends HandlerMethodArgument * @param parameter the method parameter * @param bindingContext the binding context to use * @param exchange the current exchange - * @return an {@code Optional} with the resolved value, possibly empty + * @return the resolved value, if any */ - Optional resolveArgumentValue( - MethodParameter parameter, BindingContext bindingContext, ServerWebExchange exchange); + @Nullable + Object resolveArgumentValue(MethodParameter parameter, BindingContext bindingContext, + ServerWebExchange exchange); } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/AbstractNamedValueSyncArgumentResolver.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/AbstractNamedValueSyncArgumentResolver.java index 779b11a058b..dca688438c0 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/AbstractNamedValueSyncArgumentResolver.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/AbstractNamedValueSyncArgumentResolver.java @@ -16,8 +16,6 @@ package org.springframework.web.reactive.result.method.annotation; -import java.util.Optional; - import reactor.core.publisher.Mono; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -64,13 +62,11 @@ public abstract class AbstractNamedValueSyncArgumentResolver extends AbstractNam } @Override - public Optional resolveArgumentValue( - MethodParameter parameter, BindingContext context, ServerWebExchange exchange) { + public Object resolveArgumentValue(MethodParameter parameter, BindingContext context, + ServerWebExchange exchange) { // This won't block since resolveName below doesn't - Object value = resolveArgument(parameter, context, exchange).block(); - - return Optional.ofNullable(value); + return resolveArgument(parameter, context, exchange).block(); } @Override diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ControllerMethodResolver.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ControllerMethodResolver.java index e503658edb9..3c9c9783665 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ControllerMethodResolver.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ControllerMethodResolver.java @@ -21,7 +21,6 @@ import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; @@ -53,7 +52,7 @@ import org.springframework.web.reactive.result.method.InvocableHandlerMethod; import org.springframework.web.reactive.result.method.SyncHandlerMethodArgumentResolver; import org.springframework.web.reactive.result.method.SyncInvocableHandlerMethod; -import static org.springframework.core.MethodIntrospector.*; +import static org.springframework.core.MethodIntrospector.selectMethods; /** * Package-private class to assist {@link RequestMappingHandlerAdapter} with @@ -284,8 +283,8 @@ class ControllerMethodResolver { * Find an {@code @ExceptionHandler} method in {@code @ControllerAdvice} * components or in the controller of the given {@code @RequestMapping} method. */ - public Optional getExceptionHandlerMethod(Throwable ex, - HandlerMethod handlerMethod) { + @Nullable + public InvocableHandlerMethod getExceptionHandlerMethod(Throwable ex, HandlerMethod handlerMethod) { Class handlerType = handlerMethod.getBeanType(); @@ -309,12 +308,12 @@ class ControllerMethodResolver { } if (targetMethod == null) { - return Optional.empty(); + return null; } InvocableHandlerMethod invocable = new InvocableHandlerMethod(targetBean, targetMethod); invocable.setArgumentResolvers(this.exceptionHandlerResolvers); - return Optional.of(invocable); + return invocable; } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ModelArgumentResolver.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ModelArgumentResolver.java index d34f3b87c8a..5f221793488 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ModelArgumentResolver.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ModelArgumentResolver.java @@ -16,8 +16,6 @@ package org.springframework.web.reactive.result.method.annotation; -import java.util.Optional; - import org.springframework.core.MethodParameter; import org.springframework.core.ReactiveAdapterRegistry; import org.springframework.ui.Model; @@ -47,11 +45,11 @@ public class ModelArgumentResolver extends HandlerMethodArgumentResolverSupport } @Override - public Optional resolveArgumentValue(MethodParameter methodParameter, - BindingContext context, ServerWebExchange exchange) { + public Object resolveArgumentValue(MethodParameter methodParameter, BindingContext context, + ServerWebExchange exchange) { Assert.isAssignable(Model.class, methodParameter.getParameterType()); - return Optional.of(context.getModel()); + return context.getModel(); } } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/PathVariableMapMethodArgumentResolver.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/PathVariableMapMethodArgumentResolver.java index 1c5a801e0b6..9cd93e005ec 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/PathVariableMapMethodArgumentResolver.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/PathVariableMapMethodArgumentResolver.java @@ -18,7 +18,6 @@ package org.springframework.web.reactive.result.method.annotation; import java.util.Collections; import java.util.Map; -import java.util.Optional; import org.springframework.core.MethodParameter; import org.springframework.core.ReactiveAdapterRegistry; @@ -59,12 +58,11 @@ public class PathVariableMapMethodArgumentResolver extends HandlerMethodArgument @Override - public Optional resolveArgumentValue(MethodParameter methodParameter, - BindingContext context, ServerWebExchange exchange) { + public Object resolveArgumentValue(MethodParameter methodParameter, BindingContext context, + ServerWebExchange exchange) { String name = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE; - Object value = exchange.getAttributeOrDefault(name, Collections.emptyMap()); - return Optional.of(value); + return exchange.getAttributeOrDefault(name, Collections.emptyMap()); } } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestHeaderMapMethodArgumentResolver.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestHeaderMapMethodArgumentResolver.java index db9ed78fe2a..8ee570a97a6 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestHeaderMapMethodArgumentResolver.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestHeaderMapMethodArgumentResolver.java @@ -17,7 +17,6 @@ package org.springframework.web.reactive.result.method.annotation; import java.util.Map; -import java.util.Optional; import org.springframework.core.MethodParameter; import org.springframework.core.ReactiveAdapterRegistry; @@ -61,14 +60,14 @@ public class RequestHeaderMapMethodArgumentResolver extends HandlerMethodArgumen @Override - public Optional resolveArgumentValue(MethodParameter methodParameter, + public Object resolveArgumentValue(MethodParameter methodParameter, BindingContext context, ServerWebExchange exchange) { Class paramType = methodParameter.getParameterType(); boolean isMultiValueMap = MultiValueMap.class.isAssignableFrom(paramType); HttpHeaders headers = exchange.getRequest().getHeaders(); - return Optional.of(isMultiValueMap ? headers : headers.toSingleValueMap()); + return isMultiValueMap ? headers : headers.toSingleValueMap(); } } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerAdapter.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerAdapter.java index 41037f25bb5..2def9f1a6a6 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerAdapter.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerAdapter.java @@ -197,24 +197,23 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, Application private Mono handleException(Throwable ex, HandlerMethod handlerMethod, BindingContext bindingContext, ServerWebExchange exchange) { - return this.methodResolver.getExceptionHandlerMethod(ex, handlerMethod) - .map(invocable -> { - try { - if (logger.isDebugEnabled()) { - logger.debug("Invoking @ExceptionHandler method: " + invocable.getMethod()); - } - bindingContext.getModel().asMap().clear(); - Throwable cause = ex.getCause() != null ? ex.getCause() : ex; - return invocable.invoke(exchange, bindingContext, cause, handlerMethod); - } - catch (Throwable invocationEx) { - if (logger.isWarnEnabled()) { - logger.warn("Failed to invoke: " + invocable.getMethod(), invocationEx); - } - return null; - } - }) - .orElseGet(() -> Mono.error(ex)); + InvocableHandlerMethod invocable = this.methodResolver.getExceptionHandlerMethod(ex, handlerMethod); + if (invocable != null) { + try { + if (logger.isDebugEnabled()) { + logger.debug("Invoking @ExceptionHandler method: " + invocable.getMethod()); + } + bindingContext.getModel().asMap().clear(); + Throwable cause = ex.getCause() != null ? ex.getCause() : ex; + return invocable.invoke(exchange, bindingContext, cause, handlerMethod); + } + catch (Throwable invocationEx) { + if (logger.isWarnEnabled()) { + logger.warn("Failed to invoke: " + invocable.getMethod(), invocationEx); + } + } + } + return Mono.error(ex); } } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestParamMapMethodArgumentResolver.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestParamMapMethodArgumentResolver.java index faf13bd4954..32f59681e57 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestParamMapMethodArgumentResolver.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestParamMapMethodArgumentResolver.java @@ -17,7 +17,6 @@ package org.springframework.web.reactive.result.method.annotation; import java.util.Map; -import java.util.Optional; import org.springframework.core.MethodParameter; import org.springframework.core.ReactiveAdapterRegistry; @@ -65,13 +64,12 @@ public class RequestParamMapMethodArgumentResolver extends HandlerMethodArgument @Override - public Optional resolveArgumentValue(MethodParameter methodParameter, - BindingContext context, ServerWebExchange exchange) { + public Object resolveArgumentValue(MethodParameter methodParameter, BindingContext context, + ServerWebExchange exchange) { boolean isMultiValueMap = MultiValueMap.class.isAssignableFrom(methodParameter.getParameterType()); MultiValueMap queryParams = exchange.getRequest().getQueryParams(); - Object value = isMultiValueMap ? queryParams : queryParams.toSingleValueMap(); - return Optional.of(value); + return isMultiValueMap ? queryParams : queryParams.toSingleValueMap(); } } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ServerWebExchangeArgumentResolver.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ServerWebExchangeArgumentResolver.java index 5dfb8867ee4..51e959882ea 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ServerWebExchangeArgumentResolver.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ServerWebExchangeArgumentResolver.java @@ -16,8 +16,6 @@ package org.springframework.web.reactive.result.method.annotation; -import java.util.Optional; - import org.springframework.core.MethodParameter; import org.springframework.core.ReactiveAdapterRegistry; import org.springframework.http.HttpMethod; @@ -63,21 +61,21 @@ public class ServerWebExchangeArgumentResolver extends HandlerMethodArgumentReso } @Override - public Optional resolveArgumentValue(MethodParameter methodParameter, - BindingContext context, ServerWebExchange exchange) { + public Object resolveArgumentValue(MethodParameter methodParameter, BindingContext context, + ServerWebExchange exchange) { Class paramType = methodParameter.getParameterType(); if (ServerWebExchange.class.isAssignableFrom(paramType)) { - return Optional.of(exchange); + return exchange; } else if (ServerHttpRequest.class.isAssignableFrom(paramType)) { - return Optional.of(exchange.getRequest()); + return exchange.getRequest(); } else if (ServerHttpResponse.class.isAssignableFrom(paramType)) { - return Optional.of(exchange.getResponse()); + return exchange.getResponse(); } else if (HttpMethod.class == paramType) { - return Optional.ofNullable(exchange.getRequest().getMethod()); + return exchange.getRequest().getMethod(); } else { // should never happen... diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/ControllerMethodResolverTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/ControllerMethodResolverTests.java index 240863c7c5a..ef8865454f8 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/ControllerMethodResolverTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/ControllerMethodResolverTests.java @@ -187,11 +187,11 @@ public class ControllerMethodResolverTests { @Test public void exceptionHandlerArgumentResolvers() throws Exception { - Optional optional = + InvocableHandlerMethod invocable = this.methodResolver.getExceptionHandlerMethod( new ResponseStatusException(HttpStatus.BAD_REQUEST, "reason"), this.handlerMethod); - InvocableHandlerMethod invocable = optional.orElseThrow(() -> new AssertionError("No match")); + assertNotNull("No match", invocable); assertEquals(TestController.class, invocable.getBeanType()); List resolvers = invocable.getResolvers(); @@ -221,11 +221,10 @@ public class ControllerMethodResolverTests { @Test public void exceptionHandlerFromControllerAdvice() throws Exception { - Optional optional = + InvocableHandlerMethod invocable = this.methodResolver.getExceptionHandlerMethod( new IllegalStateException("reason"), this.handlerMethod); - InvocableHandlerMethod invocable = optional.orElseThrow(() -> new AssertionError("No match")); assertNotNull(invocable); assertEquals(TestControllerAdvice.class, invocable.getBeanType()); } @@ -286,7 +285,7 @@ public class ControllerMethodResolverTests { implements SyncHandlerMethodArgumentResolver { @Override - public Optional resolveArgumentValue(MethodParameter p, BindingContext c, ServerWebExchange e) { + public Object resolveArgumentValue(MethodParameter p, BindingContext c, ServerWebExchange e) { return null; } }