diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/BindingContext.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/BindingContext.java new file mode 100644 index 0000000000..6650b005a7 --- /dev/null +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/BindingContext.java @@ -0,0 +1,83 @@ +/* + * Copyright 2002-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.web.reactive.result.method; + +import reactor.core.publisher.Mono; + +import org.springframework.ui.ModelMap; +import org.springframework.validation.support.BindingAwareModelMap; +import org.springframework.web.bind.WebDataBinder; +import org.springframework.web.bind.WebExchangeDataBinder; +import org.springframework.web.bind.support.WebBindingInitializer; +import org.springframework.web.server.ServerWebExchange; + +/** + * A context for binding requests to method arguments that provides access to + * the default model, data binding, validation, and type conversion. + * + * @author Rossen Stoyanchev + * @since 5.0 + */ +public class BindingContext { + + private final ModelMap model = new BindingAwareModelMap(); + + private final WebBindingInitializer initializer; + + + public BindingContext() { + this(null); + } + + public BindingContext(WebBindingInitializer initializer) { + this.initializer = initializer; + } + + + /** + * Return the default model. + */ + public ModelMap getModel() { + return this.model; + } + + /** + * Create a {@link WebExchangeDataBinder} for the given object. + * @param exchange the current exchange + * @param target the object to create a data binder for, or {@code null} if + * creating a binder for a simple type + * @param objectName the name of the target object + * @return a Mono for the created {@link WebDataBinder} instance + */ + public Mono createBinder(ServerWebExchange exchange, Object target, + String objectName) { + + WebExchangeDataBinder dataBinder = createBinderInstance(target, objectName); + if (this.initializer != null) { + this.initializer.initBinder(dataBinder); + } + return initBinder(dataBinder, exchange); + } + + protected WebExchangeDataBinder createBinderInstance(Object target, String objectName) { + return new WebExchangeDataBinder(target, objectName); + } + + protected Mono initBinder(WebExchangeDataBinder dataBinder, ServerWebExchange exchange) { + return Mono.just(dataBinder); + } + +} diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/HandlerMethodArgumentResolver.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/HandlerMethodArgumentResolver.java index 63c0fe64bd..5b53657979 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/HandlerMethodArgumentResolver.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/HandlerMethodArgumentResolver.java @@ -19,11 +19,13 @@ package org.springframework.web.reactive.result.method; import reactor.core.publisher.Mono; import org.springframework.core.MethodParameter; -import org.springframework.ui.ModelMap; import org.springframework.web.server.ServerWebExchange; /** + * Strategy interface for resolving method parameters into argument values in + * the context of a given request. + * * @author Rossen Stoyanchev * @since 5.0 */ @@ -37,9 +39,10 @@ public interface HandlerMethodArgumentResolver { * does not resolve to any value, which will result in {@code null} passed * as the argument value. * @param parameter the method parameter - * @param model the implicit model for request handling + * @param bindingContext the binding context to use * @param exchange the current exchange */ - Mono resolveArgument(MethodParameter parameter, ModelMap model, ServerWebExchange exchange); + Mono resolveArgument(MethodParameter parameter, BindingContext bindingContext, + ServerWebExchange exchange); } diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/InvocableHandlerMethod.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/InvocableHandlerMethod.java index eeb64a7018..1ec45a7d23 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/InvocableHandlerMethod.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/InvocableHandlerMethod.java @@ -81,18 +81,19 @@ public class InvocableHandlerMethod extends HandlerMethod { /** * Invoke the method and return a Publisher for the return value. * @param exchange the current exchange - * @param model the model for request handling + * @param bindingContext the binding context to use * @param providedArgs optional list of argument values to check by type * (via {@code instanceof}) for resolving method arguments. * @return Publisher that produces a single HandlerResult or an error signal; * never throws an exception */ - public Mono invokeForRequest(ServerWebExchange exchange, ModelMap model, - Object... providedArgs) { + public Mono invokeForRequest(ServerWebExchange exchange, + BindingContext bindingContext, Object... providedArgs) { - return resolveArguments(exchange, model, providedArgs).then(args -> { + return resolveArguments(exchange, bindingContext, providedArgs).then(args -> { try { Object value = doInvoke(args); + ModelMap model = bindingContext.getModel(); HandlerResult handlerResult = new HandlerResult(this, value, getReturnType(), model); return Mono.just(handlerResult); } @@ -106,7 +107,9 @@ public class InvocableHandlerMethod extends HandlerMethod { }); } - private Mono resolveArguments(ServerWebExchange exchange, ModelMap model, Object... providedArgs) { + private Mono resolveArguments(ServerWebExchange exchange, + BindingContext bindingContext, Object... providedArgs) { + if (ObjectUtils.isEmpty(getMethodParameters())) { return NO_ARGS; } @@ -127,7 +130,7 @@ public class InvocableHandlerMethod extends HandlerMethod { .findFirst() .orElseThrow(() -> getArgError("No resolver for ", param, null)); try { - return resolver.resolveArgument(param, model, exchange) + return resolver.resolveArgument(param, bindingContext, exchange) .defaultIfEmpty(NO_VALUE) .doOnError(cause -> { if(logger.isDebugEnabled()) { diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/AbstractNamedValueMethodArgumentResolver.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/AbstractNamedValueMethodArgumentResolver.java index 0ac690d775..9b2fabb78c 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/AbstractNamedValueMethodArgumentResolver.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/AbstractNamedValueMethodArgumentResolver.java @@ -32,6 +32,7 @@ import org.springframework.core.convert.ConversionService; import org.springframework.ui.ModelMap; import org.springframework.util.Assert; import org.springframework.web.bind.annotation.ValueConstants; +import org.springframework.web.reactive.result.method.BindingContext; import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver; import org.springframework.web.server.ServerErrorException; import org.springframework.web.server.ServerWebExchange; @@ -85,7 +86,9 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle @Override - public Mono resolveArgument(MethodParameter parameter, ModelMap model, ServerWebExchange exchange) { + public Mono resolveArgument(MethodParameter parameter, BindingContext bindingContext, + ServerWebExchange exchange) { + NamedValueInfo namedValueInfo = getNamedValueInfo(parameter); MethodParameter nestedParameter = parameter.nestedIfOptional(); @@ -95,6 +98,8 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle "Specified name must not resolve to null: [" + namedValueInfo.name + "]")); } + ModelMap model = bindingContext.getModel(); + return resolveName(resolvedName.toString(), nestedParameter, exchange) .map(arg -> { if ("".equals(arg) && namedValueInfo.defaultValue != null) { diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/HttpEntityArgumentResolver.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/HttpEntityArgumentResolver.java index dea06a021b..857bbe0888 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/HttpEntityArgumentResolver.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/HttpEntityArgumentResolver.java @@ -27,8 +27,8 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.RequestEntity; import org.springframework.http.codec.HttpMessageReader; import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.ui.ModelMap; import org.springframework.validation.Validator; +import org.springframework.web.reactive.result.method.BindingContext; import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver; import org.springframework.web.server.ServerWebExchange; @@ -73,7 +73,8 @@ public class HttpEntityArgumentResolver extends AbstractMessageReaderArgumentRes } @Override - public Mono resolveArgument(MethodParameter param, ModelMap model, ServerWebExchange exchange) { + public Mono resolveArgument(MethodParameter param, BindingContext bindingContext, + ServerWebExchange exchange) { ResolvableType entityType = ResolvableType.forMethodParameter(param); MethodParameter bodyParameter = new MethodParameter(param); diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/ModelArgumentResolver.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/ModelArgumentResolver.java index 6a3df9e3a5..04da21cd7e 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/ModelArgumentResolver.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/ModelArgumentResolver.java @@ -19,7 +19,7 @@ import reactor.core.publisher.Mono; import org.springframework.core.MethodParameter; import org.springframework.ui.Model; -import org.springframework.ui.ModelMap; +import org.springframework.web.reactive.result.method.BindingContext; import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver; import org.springframework.web.server.ServerWebExchange; @@ -38,8 +38,10 @@ public class ModelArgumentResolver implements HandlerMethodArgumentResolver { } @Override - public Mono resolveArgument(MethodParameter parameter, ModelMap model, ServerWebExchange exchange) { - return Mono.just(model); + public Mono resolveArgument(MethodParameter parameter, BindingContext bindingContext, + ServerWebExchange exchange) { + + return Mono.just(bindingContext.getModel()); } } diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/PathVariableMapMethodArgumentResolver.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/PathVariableMapMethodArgumentResolver.java index 2af212fd0c..db7cbcf84a 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/PathVariableMapMethodArgumentResolver.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/PathVariableMapMethodArgumentResolver.java @@ -23,10 +23,10 @@ import java.util.Optional; import reactor.core.publisher.Mono; import org.springframework.core.MethodParameter; -import org.springframework.ui.ModelMap; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.reactive.HandlerMapping; +import org.springframework.web.reactive.result.method.BindingContext; import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver; import org.springframework.web.server.ServerWebExchange; @@ -54,7 +54,7 @@ public class PathVariableMapMethodArgumentResolver implements HandlerMethodArgum * Return a Map with all URI template variables or an empty map. */ @Override - public Mono resolveArgument(MethodParameter parameter, ModelMap model, + public Mono resolveArgument(MethodParameter parameter, BindingContext bindingContext, ServerWebExchange exchange) { String name = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE; diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolver.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolver.java index 2ea21eeb38..4fccceac8c 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolver.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolver.java @@ -23,9 +23,9 @@ import reactor.core.publisher.Mono; import org.springframework.core.MethodParameter; import org.springframework.core.ReactiveAdapterRegistry; import org.springframework.http.codec.HttpMessageReader; -import org.springframework.ui.ModelMap; import org.springframework.validation.Validator; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.reactive.result.method.BindingContext; import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.ServerWebInputException; @@ -76,7 +76,9 @@ public class RequestBodyArgumentResolver extends AbstractMessageReaderArgumentRe } @Override - public Mono resolveArgument(MethodParameter param, ModelMap model, ServerWebExchange exchange) { + public Mono resolveArgument(MethodParameter param, BindingContext bindingContext, + ServerWebExchange exchange) { + boolean isRequired = param.getParameterAnnotation(RequestBody.class).required(); return readBody(param, isRequired, exchange); } diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestHeaderMapMethodArgumentResolver.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestHeaderMapMethodArgumentResolver.java index e452dc082c..de0a387157 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestHeaderMapMethodArgumentResolver.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestHeaderMapMethodArgumentResolver.java @@ -22,9 +22,9 @@ import reactor.core.publisher.Mono; import org.springframework.core.MethodParameter; import org.springframework.http.HttpHeaders; -import org.springframework.ui.ModelMap; import org.springframework.util.MultiValueMap; import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.reactive.result.method.BindingContext; import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver; import org.springframework.web.server.ServerWebExchange; @@ -50,7 +50,9 @@ public class RequestHeaderMapMethodArgumentResolver implements HandlerMethodArgu } @Override - public Mono resolveArgument(MethodParameter parameter, ModelMap model, ServerWebExchange exchange) { + public Mono resolveArgument(MethodParameter parameter, BindingContext bindingContext, + ServerWebExchange exchange) { + HttpHeaders headers = exchange.getRequest().getHeaders(); if (MultiValueMap.class.isAssignableFrom(parameter.getParameterType())) { return Mono.just(headers); diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerAdapter.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerAdapter.java index dcfea44c00..6524ed9274 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerAdapter.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerAdapter.java @@ -38,14 +38,13 @@ import org.springframework.core.convert.ConversionService; import org.springframework.format.support.DefaultFormattingConversionService; import org.springframework.http.codec.DecoderHttpMessageReader; import org.springframework.http.codec.HttpMessageReader; -import org.springframework.ui.ExtendedModelMap; -import org.springframework.ui.ModelMap; import org.springframework.validation.Validator; import org.springframework.web.bind.support.WebBindingInitializer; import org.springframework.web.method.HandlerMethod; import org.springframework.web.method.annotation.ExceptionHandlerMethodResolver; import org.springframework.web.reactive.HandlerAdapter; import org.springframework.web.reactive.HandlerResult; +import org.springframework.web.reactive.result.method.BindingContext; import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver; import org.springframework.web.reactive.result.method.InvocableHandlerMethod; import org.springframework.web.server.ServerWebExchange; @@ -257,14 +256,16 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, BeanFactory HandlerMethod handlerMethod = (HandlerMethod) handler; InvocableHandlerMethod invocable = new InvocableHandlerMethod(handlerMethod); invocable.setHandlerMethodArgumentResolvers(getArgumentResolvers()); - ModelMap model = new ExtendedModelMap(); - return invocable.invokeForRequest(exchange, model) - .map(result -> result.setExceptionHandler(ex -> handleException(ex, handlerMethod, exchange))) - .otherwise(ex -> handleException(ex, handlerMethod, exchange)); + BindingContext bindingContext = new BindingContext(getWebBindingInitializer()); + return invocable.invokeForRequest(exchange, bindingContext) + .map(result -> result.setExceptionHandler( + ex -> handleException(ex, handlerMethod, bindingContext, exchange))) + .otherwise(ex -> handleException( + ex, handlerMethod, bindingContext, exchange)); } private Mono handleException(Throwable ex, HandlerMethod handlerMethod, - ServerWebExchange exchange) { + BindingContext bindingContext, ServerWebExchange exchange) { if (ex instanceof Exception) { InvocableHandlerMethod invocable = findExceptionHandler(handlerMethod, (Exception) ex); @@ -274,8 +275,8 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, BeanFactory logger.debug("Invoking @ExceptionHandler method: " + invocable); } invocable.setHandlerMethodArgumentResolvers(getArgumentResolvers()); - ExtendedModelMap errorModel = new ExtendedModelMap(); - return invocable.invokeForRequest(exchange, errorModel, ex); + bindingContext.getModel().clear(); + return invocable.invokeForRequest(exchange, bindingContext, ex); } catch (Exception invocationEx) { if (logger.isErrorEnabled()) { diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestParamMapMethodArgumentResolver.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestParamMapMethodArgumentResolver.java index a2ef604cc4..d93490e701 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestParamMapMethodArgumentResolver.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestParamMapMethodArgumentResolver.java @@ -21,10 +21,10 @@ import java.util.Map; import reactor.core.publisher.Mono; import org.springframework.core.MethodParameter; -import org.springframework.ui.ModelMap; import org.springframework.util.MultiValueMap; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.reactive.result.method.BindingContext; import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver; import org.springframework.web.server.ServerWebExchange; @@ -57,7 +57,9 @@ public class RequestParamMapMethodArgumentResolver implements HandlerMethodArgum } @Override - public Mono resolveArgument(MethodParameter parameter, ModelMap model, ServerWebExchange exchange) { + public Mono resolveArgument(MethodParameter parameter, BindingContext bindingContext, + ServerWebExchange exchange) { + Class paramType = parameter.getParameterType(); MultiValueMap queryParams = exchange.getRequest().getQueryParams(); if (MultiValueMap.class.isAssignableFrom(paramType)) { diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/ServerWebExchangeArgumentResolver.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/ServerWebExchangeArgumentResolver.java index 7a8d09e622..d600af0935 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/ServerWebExchangeArgumentResolver.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/ServerWebExchangeArgumentResolver.java @@ -21,7 +21,7 @@ import org.springframework.core.MethodParameter; import org.springframework.http.HttpMethod; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; -import org.springframework.ui.ModelMap; +import org.springframework.web.reactive.result.method.BindingContext; import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebSession; @@ -52,7 +52,9 @@ public class ServerWebExchangeArgumentResolver implements HandlerMethodArgumentR } @Override - public Mono resolveArgument(MethodParameter parameter, ModelMap model, ServerWebExchange exchange) { + public Mono resolveArgument(MethodParameter parameter, BindingContext bindingContext, + ServerWebExchange exchange) { + Class paramType = parameter.getParameterType(); if (ServerWebExchange.class.isAssignableFrom(paramType)) { return Mono.just(exchange); diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/InvocableHandlerMethodTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/InvocableHandlerMethodTests.java index e54994775c..7b1e2ee3c5 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/InvocableHandlerMethodTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/InvocableHandlerMethodTests.java @@ -26,8 +26,6 @@ import org.springframework.http.HttpMethod; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; import org.springframework.tests.TestSubscriber; -import org.springframework.ui.ExtendedModelMap; -import org.springframework.ui.ModelMap; import org.springframework.web.reactive.HandlerResult; import org.springframework.web.reactive.result.ResolvableMethod; import org.springframework.web.server.ServerWebExchange; @@ -50,8 +48,6 @@ public class InvocableHandlerMethodTests { private ServerWebExchange exchange; - private ModelMap model = new ExtendedModelMap(); - @Before public void setUp() throws Exception { @@ -65,7 +61,7 @@ public class InvocableHandlerMethodTests { @Test public void invokeMethodWithNoArguments() throws Exception { InvocableHandlerMethod hm = handlerMethod("noArgs"); - Mono mono = hm.invokeForRequest(this.exchange, this.model); + Mono mono = hm.invokeForRequest(this.exchange, new BindingContext()); assertHandlerResultValue(mono, "success"); } @@ -74,7 +70,7 @@ public class InvocableHandlerMethodTests { public void invokeMethodWithNoValue() throws Exception { InvocableHandlerMethod hm = handlerMethod("singleArg"); addResolver(hm, Mono.empty()); - Mono mono = hm.invokeForRequest(this.exchange, this.model); + Mono mono = hm.invokeForRequest(this.exchange, new BindingContext()); assertHandlerResultValue(mono, "success:null"); } @@ -83,7 +79,7 @@ public class InvocableHandlerMethodTests { public void invokeMethodWithValue() throws Exception { InvocableHandlerMethod hm = handlerMethod("singleArg"); addResolver(hm, Mono.just("value1")); - Mono mono = hm.invokeForRequest(this.exchange, this.model); + Mono mono = hm.invokeForRequest(this.exchange, new BindingContext()); assertHandlerResultValue(mono, "success:value1"); } @@ -91,7 +87,7 @@ public class InvocableHandlerMethodTests { @Test public void noMatchingResolver() throws Exception { InvocableHandlerMethod hm = handlerMethod("singleArg"); - Mono mono = hm.invokeForRequest(this.exchange, this.model); + Mono mono = hm.invokeForRequest(this.exchange, new BindingContext()); TestSubscriber.subscribe(mono) .assertError(IllegalStateException.class) @@ -103,7 +99,7 @@ public class InvocableHandlerMethodTests { public void resolverThrowsException() throws Exception { InvocableHandlerMethod hm = handlerMethod("singleArg"); addResolver(hm, Mono.error(new UnsupportedMediaTypeStatusException("boo"))); - Mono mono = hm.invokeForRequest(this.exchange, this.model); + Mono mono = hm.invokeForRequest(this.exchange, new BindingContext()); TestSubscriber.subscribe(mono) .assertError(UnsupportedMediaTypeStatusException.class) @@ -114,7 +110,7 @@ public class InvocableHandlerMethodTests { public void illegalArgumentExceptionIsWrappedWithInvocationDetails() throws Exception { InvocableHandlerMethod hm = handlerMethod("singleArg"); addResolver(hm, Mono.just(1)); - Mono mono = hm.invokeForRequest(this.exchange, this.model); + Mono mono = hm.invokeForRequest(this.exchange, new BindingContext()); TestSubscriber.subscribe(mono) .assertError(IllegalStateException.class) @@ -126,7 +122,7 @@ public class InvocableHandlerMethodTests { @Test public void invocationTargetExceptionIsUnwrapped() throws Exception { InvocableHandlerMethod hm = handlerMethod("exceptionMethod"); - Mono mono = hm.invokeForRequest(this.exchange, this.model); + Mono mono = hm.invokeForRequest(this.exchange, new BindingContext()); TestSubscriber.subscribe(mono) .assertError(IllegalStateException.class) diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMappingTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMappingTests.java index 9bcbf2e5e7..55f244e3d5 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMappingTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMappingTests.java @@ -35,13 +35,11 @@ import org.springframework.core.annotation.AnnotationUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; +import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; -import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.stereotype.Controller; import org.springframework.tests.TestSubscriber; -import org.springframework.ui.ExtendedModelMap; -import org.springframework.ui.ModelMap; import org.springframework.util.MultiValueMap; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PutMapping; @@ -376,8 +374,9 @@ public class RequestMappingInfoHandlerMappingTests { ServerWebExchange exchange = createExchange(HttpMethod.OPTIONS, requestURI); HandlerMethod handlerMethod = (HandlerMethod) this.handlerMapping.getHandler(exchange).block(); - ModelMap model = new ExtendedModelMap(); - Mono mono = new InvocableHandlerMethod(handlerMethod).invokeForRequest(exchange, model); + BindingContext bindingContext = new BindingContext(); + InvocableHandlerMethod invocable = new InvocableHandlerMethod(handlerMethod); + Mono mono = invocable.invokeForRequest(exchange, bindingContext); HandlerResult result = mono.block(); assertNotNull(result); diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/CookieValueMethodArgumentResolverTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/CookieValueMethodArgumentResolverTests.java index 9a3d72e0d2..f6db8ff252 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/CookieValueMethodArgumentResolverTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/CookieValueMethodArgumentResolverTests.java @@ -34,6 +34,7 @@ import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.tests.TestSubscriber; import org.springframework.web.bind.annotation.CookieValue; +import org.springframework.web.reactive.result.method.BindingContext; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.ServerWebInputException; import org.springframework.web.server.adapter.DefaultServerWebExchange; @@ -59,6 +60,8 @@ public class CookieValueMethodArgumentResolverTests { private MethodParameter cookieStringParameter; private MethodParameter stringParameter; + private BindingContext bindingContext = new BindingContext(); + @Before public void setUp() throws Exception { @@ -90,7 +93,9 @@ public class CookieValueMethodArgumentResolverTests { HttpCookie expected = new HttpCookie("name", "foo"); this.exchange.getRequest().getCookies().add(expected.getName(), expected); - Mono mono = this.resolver.resolveArgument(this.cookieParameter, null, this.exchange); + Mono mono = this.resolver.resolveArgument( + this.cookieParameter, this.bindingContext, this.exchange); + assertEquals(expected, mono.block()); } @@ -99,14 +104,16 @@ public class CookieValueMethodArgumentResolverTests { HttpCookie cookie = new HttpCookie("name", "foo"); this.exchange.getRequest().getCookies().add(cookie.getName(), cookie); - Mono mono = this.resolver.resolveArgument(this.cookieStringParameter, null, this.exchange); + Mono mono = this.resolver.resolveArgument( + this.cookieStringParameter, this.bindingContext, this.exchange); + assertEquals("Invalid result", cookie.getValue(), mono.block()); } @Test public void resolveCookieDefaultValue() { - Mono mono = this.resolver.resolveArgument(this.cookieStringParameter, null, this.exchange); - Object result = mono.block(); + Object result = this.resolver.resolveArgument( + this.cookieStringParameter, this.bindingContext, this.exchange).block(); assertTrue(result instanceof String); assertEquals("bar", result); @@ -114,7 +121,7 @@ public class CookieValueMethodArgumentResolverTests { @Test public void notFound() { - Mono mono = resolver.resolveArgument(this.cookieParameter, null, this.exchange); + Mono mono = resolver.resolveArgument(this.cookieParameter, this.bindingContext, this.exchange); TestSubscriber .subscribe(mono) .assertError(ServerWebInputException.class); diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/ExpressionValueMethodArgumentResolverTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/ExpressionValueMethodArgumentResolverTests.java index d2d4c8bfdc..6ff03b6136 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/ExpressionValueMethodArgumentResolverTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/ExpressionValueMethodArgumentResolverTests.java @@ -31,6 +31,7 @@ import org.springframework.http.HttpMethod; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.web.reactive.result.method.BindingContext; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.adapter.DefaultServerWebExchange; import org.springframework.web.server.session.MockWebSessionManager; @@ -82,7 +83,9 @@ public class ExpressionValueMethodArgumentResolverTests { public void resolveSystemProperty() throws Exception { System.setProperty("systemProperty", "22"); try { - Mono mono = this.resolver.resolveArgument(this.paramSystemProperty, null, this.exchange); + Mono mono = this.resolver.resolveArgument( + this.paramSystemProperty, new BindingContext(), this.exchange); + Object value = mono.block(); assertEquals(22, value); } diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/HttpEntityArgumentResolverTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/HttpEntityArgumentResolverTests.java index 812cc2a4eb..82c5a933e7 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/HttpEntityArgumentResolverTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/HttpEntityArgumentResolverTests.java @@ -46,9 +46,9 @@ import org.springframework.http.codec.HttpMessageReader; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; import org.springframework.tests.TestSubscriber; -import org.springframework.ui.ExtendedModelMap; import org.springframework.validation.Validator; import org.springframework.web.reactive.result.ResolvableMethod; +import org.springframework.web.reactive.result.method.BindingContext; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.ServerWebInputException; import org.springframework.web.server.adapter.DefaultServerWebExchange; @@ -304,7 +304,7 @@ public class HttpEntityArgumentResolverTests { this.request.setBody(body); MethodParameter param = this.testMethod.resolveParam(type); - Mono result = this.resolver.resolveArgument(param, new ExtendedModelMap(), this.exchange); + Mono result = this.resolver.resolveArgument(param, new BindingContext(), this.exchange); Object value = result.block(Duration.ofSeconds(5)); assertNotNull(value); @@ -317,7 +317,7 @@ public class HttpEntityArgumentResolverTests { @SuppressWarnings("unchecked") private HttpEntity resolveValueWithEmptyBody(ResolvableType type) { MethodParameter param = this.testMethod.resolveParam(type); - Mono result = this.resolver.resolveArgument(param, new ExtendedModelMap(), this.exchange); + Mono result = this.resolver.resolveArgument(param, new BindingContext(), this.exchange); HttpEntity httpEntity = (HttpEntity) result.block(Duration.ofSeconds(5)); assertEquals(this.request.getHeaders(), httpEntity.getHeaders()); diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/MessageReaderArgumentResolverTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/MessageReaderArgumentResolverTests.java index 83239607b7..81871441b3 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/MessageReaderArgumentResolverTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/MessageReaderArgumentResolverTests.java @@ -18,8 +18,6 @@ package org.springframework.web.reactive.result.method.annotation; import java.io.Serializable; import java.lang.reflect.Method; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; @@ -41,8 +39,6 @@ import rx.Single; import org.springframework.core.MethodParameter; import org.springframework.core.ResolvableType; import org.springframework.core.codec.Decoder; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.core.io.buffer.DefaultDataBufferFactory; import org.springframework.http.HttpMethod; import org.springframework.http.codec.DecoderHttpMessageReader; import org.springframework.http.codec.HttpMessageReader; @@ -61,8 +57,12 @@ import org.springframework.web.server.UnsupportedMediaTypeStatusException; import org.springframework.web.server.adapter.DefaultServerWebExchange; import org.springframework.web.server.session.MockWebSessionManager; -import static org.junit.Assert.*; -import static org.springframework.core.ResolvableType.*; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.springframework.core.ResolvableType.forClass; +import static org.springframework.core.ResolvableType.forClassWithGenerics; /** * Unit tests for {@link AbstractMessageReaderArgumentResolver}. @@ -302,12 +302,6 @@ public class MessageReaderArgumentResolverTests { return new AbstractMessageReaderArgumentResolver(readers, new TestBeanValidator()) {}; } - private DataBuffer dataBuffer(String body) { - byte[] bytes = body.getBytes(StandardCharsets.UTF_8); - ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); - return new DefaultDataBufferFactory().wrap(byteBuffer); - } - @SuppressWarnings("unused") private void handle( diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/PathVariableMapMethodArgumentResolverTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/PathVariableMapMethodArgumentResolverTests.java index 61a4bbe5bf..736a70d89a 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/PathVariableMapMethodArgumentResolverTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/PathVariableMapMethodArgumentResolverTests.java @@ -27,12 +27,12 @@ import reactor.core.publisher.Mono; import org.springframework.core.MethodParameter; import org.springframework.http.HttpMethod; +import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; -import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.reactive.HandlerMapping; +import org.springframework.web.reactive.result.method.BindingContext; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.adapter.DefaultServerWebExchange; import org.springframework.web.server.session.MockWebSessionManager; @@ -86,7 +86,7 @@ public class PathVariableMapMethodArgumentResolverTests { uriTemplateVars.put("name2", "value2"); this.exchange.getAttributes().put(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVars); - Mono mono = this.resolver.resolveArgument(this.paramMap, new ModelMap(), this.exchange); + Mono mono = this.resolver.resolveArgument(this.paramMap, new BindingContext(), this.exchange); Object result = mono.block(); assertEquals(uriTemplateVars, result); @@ -94,7 +94,7 @@ public class PathVariableMapMethodArgumentResolverTests { @Test public void resolveArgumentNoUriVars() throws Exception { - Mono mono = this.resolver.resolveArgument(this.paramMap, new ModelMap(), this.exchange); + Mono mono = this.resolver.resolveArgument(this.paramMap, new BindingContext(), this.exchange); Object result = mono.block(); assertEquals(Collections.emptyMap(), result); diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/PathVariableMethodArgumentResolverTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/PathVariableMethodArgumentResolverTests.java index c8ba4f81f9..290b2a69c0 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/PathVariableMethodArgumentResolverTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/PathVariableMethodArgumentResolverTests.java @@ -30,14 +30,14 @@ import org.springframework.core.annotation.SynthesizingMethodParameter; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.http.HttpMethod; +import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; -import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.tests.TestSubscriber; -import org.springframework.ui.ModelMap; import org.springframework.util.ReflectionUtils; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.reactive.HandlerMapping; +import org.springframework.web.reactive.result.method.BindingContext; import org.springframework.web.server.ServerErrorException; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.adapter.DefaultServerWebExchange; @@ -98,7 +98,8 @@ public class PathVariableMethodArgumentResolverTests { uriTemplateVars.put("name", "value"); this.exchange.getAttributes().put(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVars); - Mono mono = this.resolver.resolveArgument(this.paramNamedString, new ModelMap(), this.exchange); + BindingContext bindingContext = new BindingContext(); + Mono mono = this.resolver.resolveArgument(this.paramNamedString, bindingContext, this.exchange); Object result = mono.block(); assertEquals("value", result); } @@ -109,7 +110,8 @@ public class PathVariableMethodArgumentResolverTests { uriTemplateVars.put("name", "value"); this.exchange.getAttributes().put(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVars); - Mono mono = this.resolver.resolveArgument(this.paramNotRequired, new ModelMap(), this.exchange); + BindingContext bindingContext = new BindingContext(); + Mono mono = this.resolver.resolveArgument(this.paramNotRequired, bindingContext, this.exchange); Object result = mono.block(); assertEquals("value", result); } @@ -120,14 +122,16 @@ public class PathVariableMethodArgumentResolverTests { uriTemplateVars.put("name", "value"); this.exchange.getAttributes().put(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVars); - Mono mono = this.resolver.resolveArgument(this.paramOptional, new ModelMap(), this.exchange); + BindingContext bindingContext = new BindingContext(); + Mono mono = this.resolver.resolveArgument(this.paramOptional, bindingContext, this.exchange); Object result = mono.block(); assertEquals(Optional.of("value"), result); } @Test public void handleMissingValue() throws Exception { - Mono mono = this.resolver.resolveArgument(this.paramNamedString, new ModelMap(), this.exchange); + BindingContext bindingContext = new BindingContext(); + Mono mono = this.resolver.resolveArgument(this.paramNamedString, bindingContext, this.exchange); TestSubscriber .subscribe(mono) .assertError(ServerErrorException.class); @@ -135,7 +139,8 @@ public class PathVariableMethodArgumentResolverTests { @Test public void nullIfNotRequired() throws Exception { - Mono mono = this.resolver.resolveArgument(this.paramNotRequired, new ModelMap(), this.exchange); + BindingContext bindingContext = new BindingContext(); + Mono mono = this.resolver.resolveArgument(this.paramNotRequired, bindingContext, this.exchange); TestSubscriber .subscribe(mono) .assertComplete() @@ -144,7 +149,8 @@ public class PathVariableMethodArgumentResolverTests { @Test public void wrapEmptyWithOptional() throws Exception { - Mono mono = this.resolver.resolveArgument(this.paramOptional, new ModelMap(), this.exchange); + BindingContext bindingContext = new BindingContext(); + Mono mono = this.resolver.resolveArgument(this.paramOptional, bindingContext, this.exchange); Object result = mono.block(); TestSubscriber .subscribe(mono) diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestAttributeMethodArgumentResolverTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestAttributeMethodArgumentResolverTests.java index aa886d90e7..da2954b6e6 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestAttributeMethodArgumentResolverTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestAttributeMethodArgumentResolverTests.java @@ -36,6 +36,7 @@ import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.tests.TestSubscriber; import org.springframework.util.ReflectionUtils; import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.reactive.result.method.BindingContext; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.ServerWebInputException; import org.springframework.web.server.adapter.DefaultServerWebExchange; @@ -88,14 +89,14 @@ public class RequestAttributeMethodArgumentResolverTests { @Test public void resolve() throws Exception { MethodParameter param = initMethodParameter(0); - Mono mono = this.resolver.resolveArgument(param, null, this.exchange); + Mono mono = this.resolver.resolveArgument(param, new BindingContext(), this.exchange); TestSubscriber .subscribe(mono) .assertError(ServerWebInputException.class); Foo foo = new Foo(); this.exchange.getAttributes().put("foo", foo); - mono = this.resolver.resolveArgument(param, null, this.exchange); + mono = this.resolver.resolveArgument(param, new BindingContext(), this.exchange); assertSame(foo, mono.block()); } @@ -104,33 +105,34 @@ public class RequestAttributeMethodArgumentResolverTests { MethodParameter param = initMethodParameter(1); Foo foo = new Foo(); this.exchange.getAttributes().put("specialFoo", foo); - Mono mono = this.resolver.resolveArgument(param, null, this.exchange); + Mono mono = this.resolver.resolveArgument(param, new BindingContext(), this.exchange); assertSame(foo, mono.block()); } @Test public void resolveNotRequired() throws Exception { MethodParameter param = initMethodParameter(2); - Mono mono = this.resolver.resolveArgument(param, null, this.exchange); + Mono mono = this.resolver.resolveArgument(param, new BindingContext(), this.exchange); assertNull(mono.block()); Foo foo = new Foo(); this.exchange.getAttributes().put("foo", foo); - mono = this.resolver.resolveArgument(param, null, this.exchange); + mono = this.resolver.resolveArgument(param, new BindingContext(), this.exchange); assertSame(foo, mono.block()); } @Test public void resolveOptional() throws Exception { MethodParameter param = initMethodParameter(3); - Mono mono = this.resolver.resolveArgument(param, null, this.exchange); + Mono mono = this.resolver.resolveArgument(param, new BindingContext(), this.exchange); + assertNotNull(mono.block()); assertEquals(Optional.class, mono.block().getClass()); assertFalse(((Optional) mono.block()).isPresent()); Foo foo = new Foo(); this.exchange.getAttributes().put("foo", foo); - mono = this.resolver.resolveArgument(param, null, this.exchange); + mono = this.resolver.resolveArgument(param, new BindingContext(), this.exchange); assertNotNull(mono.block()); assertEquals(Optional.class, mono.block().getClass()); diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolverTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolverTests.java index e8d21fe411..f9069cf984 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolverTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolverTests.java @@ -39,10 +39,10 @@ import org.springframework.http.codec.HttpMessageReader; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; import org.springframework.tests.TestSubscriber; -import org.springframework.ui.ExtendedModelMap; import org.springframework.validation.Validator; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.reactive.result.ResolvableMethod; +import org.springframework.web.reactive.result.method.BindingContext; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.ServerWebInputException; import org.springframework.web.server.adapter.DefaultServerWebExchange; @@ -213,7 +213,7 @@ public class RequestBodyArgumentResolverTests { @SuppressWarnings("unchecked") private T resolveValueWithEmptyBody(ResolvableType bodyType, boolean isRequired) { MethodParameter param = this.testMethod.resolveParam(bodyType, requestBody(isRequired)); - Mono result = this.resolver.resolveArgument(param, new ExtendedModelMap(), this.exchange); + Mono result = this.resolver.resolveArgument(param, new BindingContext(), this.exchange); Object value = result.block(Duration.ofSeconds(5)); if (value != null) { diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestHeaderMethodArgumentResolverTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestHeaderMethodArgumentResolverTests.java index 29b93007d7..0026f5069d 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestHeaderMethodArgumentResolverTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestHeaderMethodArgumentResolverTests.java @@ -39,6 +39,7 @@ import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.tests.TestSubscriber; import org.springframework.util.ReflectionUtils; import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.reactive.result.method.BindingContext; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.ServerWebInputException; import org.springframework.web.server.adapter.DefaultServerWebExchange; @@ -70,6 +71,8 @@ public class RequestHeaderMethodArgumentResolverTests { private ServerWebExchange exchange; + private BindingContext bindingContext = new BindingContext(); + @Before public void setUp() throws Exception { @@ -107,7 +110,9 @@ public class RequestHeaderMethodArgumentResolverTests { String expected = "foo"; this.exchange.getRequest().getHeaders().add("name", expected); - Mono mono = this.resolver.resolveArgument(paramNamedDefaultValueStringHeader, null, this.exchange); + Mono mono = this.resolver.resolveArgument( + this.paramNamedDefaultValueStringHeader, this.bindingContext, this.exchange); + Object result = mono.block(); assertTrue(result instanceof String); assertEquals(expected, result); @@ -118,7 +123,9 @@ public class RequestHeaderMethodArgumentResolverTests { String[] expected = new String[] {"foo", "bar"}; this.exchange.getRequest().getHeaders().put("name", Arrays.asList(expected)); - Mono mono = this.resolver.resolveArgument(paramNamedValueStringArray, null, this.exchange); + Mono mono = this.resolver.resolveArgument( + this.paramNamedValueStringArray, this.bindingContext, this.exchange); + Object result = mono.block(); assertTrue(result instanceof String[]); assertArrayEquals(expected, (String[]) result); @@ -126,7 +133,9 @@ public class RequestHeaderMethodArgumentResolverTests { @Test public void resolveDefaultValue() throws Exception { - Mono mono = this.resolver.resolveArgument(paramNamedDefaultValueStringHeader, null, this.exchange); + Mono mono = this.resolver.resolveArgument( + this.paramNamedDefaultValueStringHeader, this.bindingContext, this.exchange); + Object result = mono.block(); assertTrue(result instanceof String); assertEquals("bar", result); @@ -136,7 +145,9 @@ public class RequestHeaderMethodArgumentResolverTests { public void resolveDefaultValueFromSystemProperty() throws Exception { System.setProperty("systemProperty", "bar"); try { - Mono mono = this.resolver.resolveArgument(paramSystemProperty, null, this.exchange); + Mono mono = this.resolver.resolveArgument( + this.paramSystemProperty, this.bindingContext, this.exchange); + Object result = mono.block(); assertTrue(result instanceof String); assertEquals("bar", result); @@ -153,7 +164,9 @@ public class RequestHeaderMethodArgumentResolverTests { System.setProperty("systemProperty", "bar"); try { - Mono mono = this.resolver.resolveArgument(paramResolvedNameWithExpression, null, this.exchange); + Mono mono = this.resolver.resolveArgument( + this.paramResolvedNameWithExpression, this.bindingContext, this.exchange); + Object result = mono.block(); assertTrue(result instanceof String); assertEquals(expected, result); @@ -170,7 +183,9 @@ public class RequestHeaderMethodArgumentResolverTests { System.setProperty("systemProperty", "bar"); try { - Mono mono = this.resolver.resolveArgument(paramResolvedNameWithPlaceholder, null, this.exchange); + Mono mono = this.resolver.resolveArgument( + this.paramResolvedNameWithPlaceholder, this.bindingContext, this.exchange); + Object result = mono.block(); assertTrue(result instanceof String); assertEquals(expected, result); @@ -182,7 +197,9 @@ public class RequestHeaderMethodArgumentResolverTests { @Test public void notFound() throws Exception { - Mono mono = resolver.resolveArgument(paramNamedValueStringArray, null, this.exchange); + Mono mono = resolver.resolveArgument( + this.paramNamedValueStringArray, this.bindingContext, this.exchange); + TestSubscriber .subscribe(mono) .assertError(ServerWebInputException.class); @@ -194,7 +211,7 @@ public class RequestHeaderMethodArgumentResolverTests { String rfc1123val = "Thu, 21 Apr 2016 17:11:08 +0100"; this.exchange.getRequest().getHeaders().add("name", rfc1123val); - Mono mono = this.resolver.resolveArgument(paramDate, null, this.exchange); + Mono mono = this.resolver.resolveArgument(this.paramDate, this.bindingContext, this.exchange); Object result = mono.block(); assertTrue(result instanceof Date); @@ -206,7 +223,7 @@ public class RequestHeaderMethodArgumentResolverTests { String rfc1123val = "Thu, 21 Apr 2016 17:11:08 +0100"; this.exchange.getRequest().getHeaders().add("name", rfc1123val); - Mono mono = this.resolver.resolveArgument(paramInstant, null, this.exchange); + Mono mono = this.resolver.resolveArgument(this.paramInstant, this.bindingContext, this.exchange); Object result = mono.block(); assertTrue(result instanceof Instant); diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestParamMethodArgumentResolverTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestParamMethodArgumentResolverTests.java index f6e258c1c8..5a74e6aed1 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestParamMethodArgumentResolverTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestParamMethodArgumentResolverTests.java @@ -39,6 +39,7 @@ import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.tests.TestSubscriber; import org.springframework.util.ReflectionUtils; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.reactive.result.method.BindingContext; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.ServerWebInputException; import org.springframework.web.server.adapter.DefaultServerWebExchange; @@ -71,6 +72,8 @@ public class RequestParamMethodArgumentResolverTests { private MethodParameter paramNotRequired; private MethodParameter paramOptional; + private BindingContext bindingContext = new BindingContext(); + @Before @SuppressWarnings("ConfusingArgumentToVarargsMethod") public void setUp() throws Exception { @@ -117,9 +120,10 @@ public class RequestParamMethodArgumentResolverTests { String expected = "foo"; this.exchange.getRequest().getQueryParams().set("name", expected); - Mono mono = this.resolver.resolveArgument(this.paramNamedDefaultValueString, null, this.exchange); - Object result = mono.block(); + Mono mono = this.resolver.resolveArgument( + this.paramNamedDefaultValueString, this.bindingContext, this.exchange); + Object result = mono.block(); assertTrue(result instanceof String); assertEquals("Invalid result", expected, result); } @@ -129,25 +133,29 @@ public class RequestParamMethodArgumentResolverTests { String[] expected = {"foo", "bar"}; this.exchange.getRequest().getQueryParams().put("name", Arrays.asList(expected)); - Mono mono = this.resolver.resolveArgument(this.paramNamedStringArray, null, this.exchange); - Object result = mono.block(); + Mono mono = this.resolver.resolveArgument( + this.paramNamedStringArray, this.bindingContext, this.exchange); + Object result = mono.block(); assertTrue(result instanceof String[]); assertArrayEquals(expected, (String[]) result); } @Test public void resolveDefaultValue() throws Exception { - Mono mono = this.resolver.resolveArgument(paramNamedDefaultValueString, null, this.exchange); - Object result = mono.block(); + Mono mono = this.resolver.resolveArgument( + this.paramNamedDefaultValueString, this.bindingContext, this.exchange); + Object result = mono.block(); assertTrue(result instanceof String); assertEquals("Invalid result", "bar", result); } @Test public void missingRequestParam() throws Exception { - Mono mono = this.resolver.resolveArgument(paramNamedStringArray, null, this.exchange); + Mono mono = this.resolver.resolveArgument( + this.paramNamedStringArray, this.bindingContext, this.exchange); + TestSubscriber .subscribe(mono) .assertError(ServerWebInputException.class); @@ -156,57 +164,63 @@ public class RequestParamMethodArgumentResolverTests { @Test public void resolveSimpleTypeParam() throws Exception { this.exchange.getRequest().getQueryParams().set("stringNotAnnot", "plainValue"); - Mono mono = this.resolver.resolveArgument(paramStringNotAnnot, null, this.exchange); - Object result = mono.block(); + Mono mono = this.resolver.resolveArgument( + this.paramStringNotAnnot, this.bindingContext, this.exchange); + Object result = mono.block(); assertTrue(result instanceof String); assertEquals("plainValue", result); } @Test // SPR-8561 public void resolveSimpleTypeParamToNull() throws Exception { - Mono mono = this.resolver.resolveArgument(paramStringNotAnnot, null, this.exchange); - Object result = mono.block(); + Mono mono = this.resolver.resolveArgument( + this.paramStringNotAnnot, this.bindingContext, this.exchange); + Object result = mono.block(); assertNull(result); } @Test // SPR-10180 public void resolveEmptyValueToDefault() throws Exception { this.exchange.getRequest().getQueryParams().set("name", ""); - Mono mono = this.resolver.resolveArgument(paramNamedDefaultValueString, null, this.exchange); - Object result = mono.block(); + Mono mono = this.resolver.resolveArgument( + this.paramNamedDefaultValueString, this.bindingContext, this.exchange); + Object result = mono.block(); assertEquals("bar", result); } @Test public void resolveEmptyValueWithoutDefault() throws Exception { this.exchange.getRequest().getQueryParams().set("stringNotAnnot", ""); - Mono mono = this.resolver.resolveArgument(paramStringNotAnnot, null, this.exchange); - Object result = mono.block(); + Mono mono = this.resolver.resolveArgument( + this.paramStringNotAnnot, this.bindingContext, this.exchange); + Object result = mono.block(); assertEquals("", result); } @Test public void resolveEmptyValueRequiredWithoutDefault() throws Exception { this.exchange.getRequest().getQueryParams().set("name", ""); - Mono mono = this.resolver.resolveArgument(paramRequired, null, this.exchange); - Object result = mono.block(); + Mono mono = this.resolver.resolveArgument( + this.paramRequired, this.bindingContext, this.exchange); + Object result = mono.block(); assertEquals("", result); } @Test public void resolveOptionalParamValue() throws Exception { - Mono mono = this.resolver.resolveArgument(paramOptional, null, this.exchange); - Object result = mono.block(); + Mono mono = this.resolver.resolveArgument( + this.paramOptional, this.bindingContext, this.exchange); + Object result = mono.block(); assertEquals(Optional.empty(), result); this.exchange.getRequest().getQueryParams().set("name", "123"); - mono = resolver.resolveArgument(paramOptional, null, this.exchange); + mono = this.resolver.resolveArgument(this.paramOptional, this.bindingContext, this.exchange); result = mono.block(); assertEquals(Optional.class, result.getClass()); diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/ServerWebExchangeArgumentResolverTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/ServerWebExchangeArgumentResolverTests.java index 9fb6075cb8..14a996a463 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/ServerWebExchangeArgumentResolverTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/ServerWebExchangeArgumentResolverTests.java @@ -21,12 +21,12 @@ import reactor.core.publisher.Mono; import org.springframework.core.MethodParameter; import org.springframework.http.HttpMethod; -import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; -import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; -import org.springframework.ui.ModelMap; +import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; +import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; import org.springframework.web.reactive.result.ResolvableMethod; +import org.springframework.web.reactive.result.method.BindingContext; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebSession; import org.springframework.web.server.adapter.DefaultServerWebExchange; @@ -84,7 +84,7 @@ public class ServerWebExchangeArgumentResolverTests { } private void testResolveArgument(MethodParameter parameter, Object expected) { - Mono mono = this.resolver.resolveArgument(parameter, new ModelMap(), this.exchange); + Mono mono = this.resolver.resolveArgument(parameter, new BindingContext(), this.exchange); assertSame(expected, mono.block()); } diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SessionAttributeMethodArgumentResolverTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SessionAttributeMethodArgumentResolverTests.java index 8c049f3645..e1dabd51d6 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SessionAttributeMethodArgumentResolverTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SessionAttributeMethodArgumentResolverTests.java @@ -36,6 +36,7 @@ import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.tests.TestSubscriber; import org.springframework.util.ReflectionUtils; import org.springframework.web.bind.annotation.SessionAttribute; +import org.springframework.web.reactive.result.method.BindingContext; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.ServerWebInputException; import org.springframework.web.server.WebSession; @@ -95,14 +96,14 @@ public class SessionAttributeMethodArgumentResolverTests { @Test public void resolve() throws Exception { MethodParameter param = initMethodParameter(0); - Mono mono = this.resolver.resolveArgument(param, null, this.exchange); + Mono mono = this.resolver.resolveArgument(param, new BindingContext(), this.exchange); TestSubscriber .subscribe(mono) .assertError(ServerWebInputException.class); Foo foo = new Foo(); when(this.session.getAttribute("foo")).thenReturn(Optional.of(foo)); - mono = this.resolver.resolveArgument(param, null, this.exchange); + mono = this.resolver.resolveArgument(param, new BindingContext(), this.exchange); assertSame(foo, mono.block()); } @@ -111,33 +112,33 @@ public class SessionAttributeMethodArgumentResolverTests { MethodParameter param = initMethodParameter(1); Foo foo = new Foo(); when(this.session.getAttribute("specialFoo")).thenReturn(Optional.of(foo)); - Mono mono = this.resolver.resolveArgument(param, null, this.exchange); + Mono mono = this.resolver.resolveArgument(param, new BindingContext(), this.exchange); assertSame(foo, mono.block()); } @Test public void resolveNotRequired() throws Exception { MethodParameter param = initMethodParameter(2); - Mono mono = this.resolver.resolveArgument(param, null, this.exchange); + Mono mono = this.resolver.resolveArgument(param, new BindingContext(), this.exchange); assertNull(mono.block()); Foo foo = new Foo(); when(this.session.getAttribute("foo")).thenReturn(Optional.of(foo)); - mono = this.resolver.resolveArgument(param, null, this.exchange); + mono = this.resolver.resolveArgument(param, new BindingContext(), this.exchange); assertSame(foo, mono.block()); } @Test public void resolveOptional() throws Exception { MethodParameter param = initMethodParameter(3); - Mono mono = this.resolver.resolveArgument(param, null, this.exchange); + Mono mono = this.resolver.resolveArgument(param, new BindingContext(), this.exchange); assertNotNull(mono.block()); assertEquals(Optional.class, mono.block().getClass()); assertFalse(((Optional) mono.block()).isPresent()); Foo foo = new Foo(); when(this.session.getAttribute("foo")).thenReturn(Optional.of(foo)); - mono = this.resolver.resolveArgument(param, null, this.exchange); + mono = this.resolver.resolveArgument(param, new BindingContext(), this.exchange); assertNotNull(mono.block()); assertEquals(Optional.class, mono.block().getClass());