Reactive type checks for all argument method resolvers
All method argument resolvers now explicitly check for the presence of a reactive type wrapper and reject it where not expected. Issue: SPR-15297
This commit is contained in:
parent
a04fef8450
commit
164204ca04
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Copyright 2002-2017 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 java.lang.annotation.Annotation;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Base class for {@link HandlerMethodArgumentResolver} implementations with
|
||||
* access to a {@code ReactiveAdapterRegistry} and methods to check for
|
||||
* method parameter support.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public abstract class HandlerMethodArgumentResolverSupport {
|
||||
|
||||
private final ReactiveAdapterRegistry adapterRegistry;
|
||||
|
||||
|
||||
protected HandlerMethodArgumentResolverSupport(ReactiveAdapterRegistry adapterRegistry) {
|
||||
Assert.notNull(adapterRegistry, "ReactiveAdapterRegistry is required");
|
||||
this.adapterRegistry = adapterRegistry;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the configured {@link ReactiveAdapterRegistry}.
|
||||
*/
|
||||
public ReactiveAdapterRegistry getAdapterRegistry() {
|
||||
return this.adapterRegistry;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Evaluate the {@code Predicate} on the the method parameter type or on
|
||||
* the generic type within a reactive type wrapper.
|
||||
*/
|
||||
protected boolean checkParamType(MethodParameter param, Predicate<Class<?>> predicate) {
|
||||
Class<?> type = param.getParameterType();
|
||||
ReactiveAdapter adapter = getAdapterRegistry().getAdapter(type);
|
||||
if (adapter != null) {
|
||||
assertHasValues(adapter, param);
|
||||
type = param.nested().getNestedParameterType();
|
||||
}
|
||||
return predicate.test(type);
|
||||
}
|
||||
|
||||
private void assertHasValues(ReactiveAdapter adapter, MethodParameter param) {
|
||||
if (adapter.isNoValue()) {
|
||||
throw new IllegalArgumentException(
|
||||
"No value reactive types not supported: " + param.getGenericParameterType());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the {@code Predicate} on the method parameter type but raise an
|
||||
* {@code IllegalStateException} if the same matches the generic type
|
||||
* within a reactive type wrapper.
|
||||
*/
|
||||
protected boolean checkParamTypeNoReactiveWrapper(MethodParameter param, Predicate<Class<?>> predicate) {
|
||||
Class<?> type = param.getParameterType();
|
||||
ReactiveAdapter adapter = getAdapterRegistry().getAdapter(type);
|
||||
if (adapter != null) {
|
||||
assertHasValues(adapter, param);
|
||||
type = param.nested().getNestedParameterType();
|
||||
}
|
||||
if (predicate.test(type)) {
|
||||
if (adapter == null) {
|
||||
return true;
|
||||
}
|
||||
throw getReactiveWrapperError(param);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private IllegalStateException getReactiveWrapperError(MethodParameter param) {
|
||||
return new IllegalStateException(getClass().getSimpleName() +
|
||||
" doesn't support reactive type wrapper: " + param.getGenericParameterType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the {@code Predicate} on the method parameter type if it has the
|
||||
* given annotation, nesting within {@link java.util.Optional} if necessary,
|
||||
* but raise an {@code IllegalStateException} if the same matches the generic
|
||||
* type within a reactive type wrapper.
|
||||
*/
|
||||
protected <A extends Annotation> boolean checkAnnotatedParamNoReactiveWrapper(
|
||||
MethodParameter param, Class<A> annotationType,
|
||||
BiPredicate<A, Class<?>> typePredicate) {
|
||||
|
||||
A annotation = param.getParameterAnnotation(annotationType);
|
||||
if (annotation == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
param = param.nestedIfOptional();
|
||||
Class<?> type = param.getNestedParameterType();
|
||||
|
||||
ReactiveAdapter adapter = getAdapterRegistry().getAdapter(type);
|
||||
if (adapter != null) {
|
||||
assertHasValues(adapter, param);
|
||||
param = param.nested();
|
||||
type = param.getNestedParameterType();
|
||||
}
|
||||
|
||||
if (typePredicate.test(annotation, type)) {
|
||||
if (adapter == null) {
|
||||
return true;
|
||||
}
|
||||
throw getReactiveWrapperError(param);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -42,6 +42,7 @@ import org.springframework.validation.annotation.Validated;
|
|||
import org.springframework.web.bind.support.WebExchangeBindException;
|
||||
import org.springframework.web.bind.support.WebExchangeDataBinder;
|
||||
import org.springframework.web.reactive.BindingContext;
|
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolverSupport;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.ServerWebInputException;
|
||||
import org.springframework.web.server.UnsupportedMediaTypeStatusException;
|
||||
|
|
@ -58,12 +59,10 @@ import org.springframework.web.server.UnsupportedMediaTypeStatusException;
|
|||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public abstract class AbstractMessageReaderArgumentResolver {
|
||||
public abstract class AbstractMessageReaderArgumentResolver extends HandlerMethodArgumentResolverSupport {
|
||||
|
||||
private final List<HttpMessageReader<?>> messageReaders;
|
||||
|
||||
private final ReactiveAdapterRegistry adapterRegistry;
|
||||
|
||||
private final List<MediaType> supportedMediaTypes;
|
||||
|
||||
|
||||
|
|
@ -83,10 +82,10 @@ public abstract class AbstractMessageReaderArgumentResolver {
|
|||
protected AbstractMessageReaderArgumentResolver(List<HttpMessageReader<?>> messageReaders,
|
||||
ReactiveAdapterRegistry adapterRegistry) {
|
||||
|
||||
super(adapterRegistry);
|
||||
Assert.notEmpty(messageReaders, "At least one HttpMessageReader is required.");
|
||||
Assert.notNull(adapterRegistry, "'adapterRegistry' is required");
|
||||
this.messageReaders = messageReaders;
|
||||
this.adapterRegistry = adapterRegistry;
|
||||
this.supportedMediaTypes = messageReaders.stream()
|
||||
.flatMap(converter -> converter.getReadableMediaTypes().stream())
|
||||
.collect(Collectors.toList());
|
||||
|
|
@ -100,13 +99,6 @@ public abstract class AbstractMessageReaderArgumentResolver {
|
|||
return this.messageReaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the configured {@link ReactiveAdapterRegistry}.
|
||||
*/
|
||||
public ReactiveAdapterRegistry getAdapterRegistry() {
|
||||
return this.adapterRegistry;
|
||||
}
|
||||
|
||||
|
||||
protected Mono<Object> readBody(MethodParameter bodyParameter, boolean isBodyRequired,
|
||||
BindingContext bindingContext, ServerWebExchange exchange) {
|
||||
|
|
|
|||
|
|
@ -27,11 +27,13 @@ import org.springframework.beans.factory.config.BeanExpressionContext;
|
|||
import org.springframework.beans.factory.config.BeanExpressionResolver;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.bind.annotation.ValueConstants;
|
||||
import org.springframework.web.reactive.BindingContext;
|
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolverSupport;
|
||||
import org.springframework.web.server.ServerErrorException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.ServerWebInputException;
|
||||
|
|
@ -56,7 +58,8 @@ import org.springframework.web.server.ServerWebInputException;
|
|||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public abstract class AbstractNamedValueArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
public abstract class AbstractNamedValueArgumentResolver extends HandlerMethodArgumentResolverSupport
|
||||
implements HandlerMethodArgumentResolver {
|
||||
|
||||
private final ConfigurableBeanFactory configurableBeanFactory;
|
||||
|
||||
|
|
@ -69,8 +72,12 @@ public abstract class AbstractNamedValueArgumentResolver implements HandlerMetho
|
|||
* @param beanFactory a bean factory to use for resolving ${...} placeholder
|
||||
* and #{...} SpEL expressions in default values, or {@code null} if default
|
||||
* values are not expected to contain expressions
|
||||
* @param adapterRegistry for checking reactive type wrappers
|
||||
*/
|
||||
public AbstractNamedValueArgumentResolver(ConfigurableBeanFactory beanFactory) {
|
||||
public AbstractNamedValueArgumentResolver(ConfigurableBeanFactory beanFactory,
|
||||
ReactiveAdapterRegistry adapterRegistry) {
|
||||
|
||||
super(adapterRegistry);
|
||||
this.configurableBeanFactory = beanFactory;
|
||||
this.expressionContext = (beanFactory != null ? new BeanExpressionContext(beanFactory, null) : null);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import reactor.core.publisher.Mono;
|
|||
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.web.reactive.BindingContext;
|
||||
import org.springframework.web.reactive.result.method.SyncHandlerMethodArgumentResolver;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
|
@ -39,8 +40,16 @@ public abstract class AbstractNamedValueSyncArgumentResolver extends AbstractNam
|
|||
implements SyncHandlerMethodArgumentResolver {
|
||||
|
||||
|
||||
protected AbstractNamedValueSyncArgumentResolver(ConfigurableBeanFactory beanFactory) {
|
||||
super(beanFactory);
|
||||
/**
|
||||
* @param beanFactory a bean factory to use for resolving ${...}
|
||||
* placeholder and #{...} SpEL expressions in default values;
|
||||
* or {@code null} if default values are not expected to have expressions
|
||||
* @param adapterRegistry for checking reactive type wrappers
|
||||
*/
|
||||
protected AbstractNamedValueSyncArgumentResolver(ConfigurableBeanFactory beanFactory,
|
||||
ReactiveAdapterRegistry adapterRegistry) {
|
||||
|
||||
super(beanFactory, adapterRegistry);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import java.util.Optional;
|
|||
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.http.HttpCookie;
|
||||
import org.springframework.web.bind.annotation.CookieValue;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
|
@ -42,15 +43,18 @@ public class CookieValueMethodArgumentResolver extends AbstractNamedValueSyncArg
|
|||
* @param beanFactory a bean factory to use for resolving ${...}
|
||||
* placeholder and #{...} SpEL expressions in default values;
|
||||
* or {@code null} if default values are not expected to contain expressions
|
||||
* @param adapterRegistry for checking reactive type wrappers
|
||||
*/
|
||||
public CookieValueMethodArgumentResolver(ConfigurableBeanFactory beanFactory) {
|
||||
super(beanFactory);
|
||||
public CookieValueMethodArgumentResolver(ConfigurableBeanFactory beanFactory,
|
||||
ReactiveAdapterRegistry adapterRegistry) {
|
||||
|
||||
super(beanFactory, adapterRegistry);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return parameter.hasParameterAnnotation(CookieValue.class);
|
||||
public boolean supportsParameter(MethodParameter param) {
|
||||
return checkAnnotatedParamNoReactiveWrapper(param, CookieValue.class, (annot, type) -> true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import org.springframework.validation.Errors;
|
|||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.reactive.BindingContext;
|
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolverSupport;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
/**
|
||||
|
|
@ -40,33 +41,18 @@ import org.springframework.web.server.ServerWebExchange;
|
|||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public class ErrorsMethodArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
|
||||
private final ReactiveAdapterRegistry adapterRegistry;
|
||||
public class ErrorsMethodArgumentResolver extends HandlerMethodArgumentResolverSupport
|
||||
implements HandlerMethodArgumentResolver {
|
||||
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
* @param registry for adapting to other reactive types from and to Mono
|
||||
*/
|
||||
public ErrorsMethodArgumentResolver(ReactiveAdapterRegistry registry) {
|
||||
Assert.notNull(registry, "'ReactiveAdapterRegistry' is required.");
|
||||
this.adapterRegistry = registry;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the configured {@link ReactiveAdapterRegistry}.
|
||||
*/
|
||||
public ReactiveAdapterRegistry getAdapterRegistry() {
|
||||
return this.adapterRegistry;
|
||||
super(registry);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
Class<?> clazz = parameter.getParameterType();
|
||||
return Errors.class.isAssignableFrom(clazz);
|
||||
return checkParamTypeNoReactiveWrapper(parameter, Errors.class::isAssignableFrom);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import java.util.Optional;
|
|||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
/**
|
||||
|
|
@ -40,15 +41,18 @@ public class ExpressionValueMethodArgumentResolver extends AbstractNamedValueSyn
|
|||
* @param beanFactory a bean factory to use for resolving ${...}
|
||||
* placeholder and #{...} SpEL expressions in default values;
|
||||
* or {@code null} if default values are not expected to contain expressions
|
||||
* @param adapterRegistry for checking reactive type wrappers
|
||||
*/
|
||||
public ExpressionValueMethodArgumentResolver(ConfigurableBeanFactory beanFactory) {
|
||||
super(beanFactory);
|
||||
public ExpressionValueMethodArgumentResolver(ConfigurableBeanFactory beanFactory,
|
||||
ReactiveAdapterRegistry adapterRegistry) {
|
||||
|
||||
super(beanFactory, adapterRegistry);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return parameter.hasParameterAnnotation(Value.class);
|
||||
public boolean supportsParameter(MethodParameter param) {
|
||||
return checkAnnotatedParamNoReactiveWrapper(param, Value.class, (annot, type) -> true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ import org.springframework.http.HttpEntity;
|
|||
import org.springframework.http.RequestEntity;
|
||||
import org.springframework.http.codec.HttpMessageReader;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.validation.Validator;
|
||||
import org.springframework.web.reactive.BindingContext;
|
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
|
@ -42,19 +41,7 @@ import org.springframework.web.server.ServerWebExchange;
|
|||
public class HttpEntityArgumentResolver extends AbstractMessageReaderArgumentResolver
|
||||
implements HandlerMethodArgumentResolver {
|
||||
|
||||
/**
|
||||
* Constructor with {@link HttpMessageReader}'s and a {@link Validator}.
|
||||
* @param readers readers for de-serializing the request body with
|
||||
*/
|
||||
public HttpEntityArgumentResolver(List<HttpMessageReader<?>> readers) {
|
||||
super(readers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that also accepts a {@link ReactiveAdapterRegistry}.
|
||||
* @param readers readers for de-serializing the request body with
|
||||
* @param registry for adapting to other reactive types from Flux and Mono
|
||||
*/
|
||||
public HttpEntityArgumentResolver(List<HttpMessageReader<?>> readers, ReactiveAdapterRegistry registry) {
|
||||
super(readers, registry);
|
||||
}
|
||||
|
|
@ -62,8 +49,8 @@ public class HttpEntityArgumentResolver extends AbstractMessageReaderArgumentRes
|
|||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
Class<?> clazz = parameter.getParameterType();
|
||||
return (HttpEntity.class.equals(clazz) || RequestEntity.class.equals(clazz));
|
||||
return checkParamTypeNoReactiveWrapper(parameter,
|
||||
type -> HttpEntity.class.equals(type) || RequestEntity.class.equals(type));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -19,8 +19,11 @@ 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;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.reactive.BindingContext;
|
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolverSupport;
|
||||
import org.springframework.web.reactive.result.method.SyncHandlerMethodArgumentResolver;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
|
|
@ -30,18 +33,25 @@ import org.springframework.web.server.ServerWebExchange;
|
|||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public class ModelArgumentResolver implements SyncHandlerMethodArgumentResolver {
|
||||
public class ModelArgumentResolver extends HandlerMethodArgumentResolverSupport
|
||||
implements SyncHandlerMethodArgumentResolver {
|
||||
|
||||
|
||||
public ModelArgumentResolver(ReactiveAdapterRegistry adapterRegistry) {
|
||||
super(adapterRegistry);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return Model.class.isAssignableFrom(parameter.getParameterType());
|
||||
return checkParamTypeNoReactiveWrapper(parameter, Model.class::isAssignableFrom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Object> resolveArgumentValue(MethodParameter methodParameter,
|
||||
BindingContext context, ServerWebExchange exchange) {
|
||||
|
||||
Assert.isAssignable(Model.class, methodParameter.getParameterType());
|
||||
return Optional.of(context.getModel());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ import org.springframework.web.bind.support.WebExchangeBindException;
|
|||
import org.springframework.web.bind.support.WebExchangeDataBinder;
|
||||
import org.springframework.web.reactive.BindingContext;
|
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolverSupport;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
/**
|
||||
|
|
@ -59,42 +60,24 @@ import org.springframework.web.server.ServerWebExchange;
|
|||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public class ModelAttributeMethodArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
|
||||
private final ReactiveAdapterRegistry adapterRegistry;
|
||||
public class ModelAttributeMethodArgumentResolver extends HandlerMethodArgumentResolverSupport
|
||||
implements HandlerMethodArgumentResolver {
|
||||
|
||||
private final boolean useDefaultResolution;
|
||||
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
* @param registry for adapting to other reactive types from and to Mono
|
||||
*/
|
||||
public ModelAttributeMethodArgumentResolver(ReactiveAdapterRegistry registry) {
|
||||
this(registry, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor with a default resolution mode flag.
|
||||
* @param registry for adapting to other reactive types from and to Mono
|
||||
* @param adapterRegistry for adapting to other reactive types from and to Mono
|
||||
* @param useDefaultResolution if "true", non-simple method arguments and
|
||||
* return values are considered model attributes with or without a
|
||||
* {@code @ModelAttribute} annotation present.
|
||||
*/
|
||||
public ModelAttributeMethodArgumentResolver(ReactiveAdapterRegistry registry,
|
||||
public ModelAttributeMethodArgumentResolver(ReactiveAdapterRegistry adapterRegistry,
|
||||
boolean useDefaultResolution) {
|
||||
|
||||
Assert.notNull(registry, "'ReactiveAdapterRegistry' is required.");
|
||||
super(adapterRegistry);
|
||||
this.useDefaultResolution = useDefaultResolution;
|
||||
this.adapterRegistry = registry;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the configured {@link ReactiveAdapterRegistry}.
|
||||
*/
|
||||
public ReactiveAdapterRegistry getAdapterRegistry() {
|
||||
return this.adapterRegistry;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -103,16 +86,8 @@ public class ModelAttributeMethodArgumentResolver implements HandlerMethodArgume
|
|||
if (parameter.hasParameterAnnotation(ModelAttribute.class)) {
|
||||
return true;
|
||||
}
|
||||
if (this.useDefaultResolution) {
|
||||
Class<?> clazz = parameter.getParameterType();
|
||||
ReactiveAdapter adapter = getAdapterRegistry().getAdapter(clazz);
|
||||
if (adapter != null) {
|
||||
if (adapter.isNoValue() || adapter.isMultiValue()) {
|
||||
return false;
|
||||
}
|
||||
clazz = parameter.nested().getNestedParameterType();
|
||||
}
|
||||
return !BeanUtils.isSimpleProperty(clazz);
|
||||
else if (this.useDefaultResolution) {
|
||||
return checkParamType(parameter, type -> !BeanUtils.isSimpleProperty(type));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -125,6 +100,10 @@ public class ModelAttributeMethodArgumentResolver implements HandlerMethodArgume
|
|||
ReactiveAdapter adapter = getAdapterRegistry().getAdapter(type.resolve());
|
||||
ResolvableType valueType = (adapter != null ? type.getGeneric(0) : type);
|
||||
|
||||
Assert.state(adapter == null || !adapter.isMultiValue(),
|
||||
getClass().getSimpleName() + " doesn't support multi-value reactive type wrapper: " +
|
||||
parameter.getGenericParameterType());
|
||||
|
||||
String name = getAttributeName(valueType, parameter);
|
||||
Mono<?> valueMono = getAttributeMono(name, valueType, context.getModel());
|
||||
|
||||
|
|
|
|||
|
|
@ -21,10 +21,12 @@ import java.util.Map;
|
|||
import java.util.Optional;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.reactive.BindingContext;
|
||||
import org.springframework.web.reactive.HandlerMapping;
|
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolverSupport;
|
||||
import org.springframework.web.reactive.result.method.SyncHandlerMethodArgumentResolver;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
|
|
@ -38,17 +40,25 @@ import org.springframework.web.server.ServerWebExchange;
|
|||
* @since 5.0
|
||||
* @see PathVariableMethodArgumentResolver
|
||||
*/
|
||||
public class PathVariableMapMethodArgumentResolver implements SyncHandlerMethodArgumentResolver {
|
||||
public class PathVariableMapMethodArgumentResolver extends HandlerMethodArgumentResolverSupport
|
||||
implements SyncHandlerMethodArgumentResolver {
|
||||
|
||||
|
||||
public PathVariableMapMethodArgumentResolver(ReactiveAdapterRegistry adapterRegistry) {
|
||||
super(adapterRegistry);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
PathVariable annotation = parameter.getParameterAnnotation(PathVariable.class);
|
||||
return (annotation != null &&
|
||||
Map.class.isAssignableFrom(parameter.getParameterType()) &&
|
||||
!StringUtils.hasText(annotation.value()));
|
||||
return checkAnnotatedParamNoReactiveWrapper(parameter, PathVariable.class, this::allVariables);
|
||||
}
|
||||
|
||||
private boolean allVariables(PathVariable pathVariable, Class<?> type) {
|
||||
return Map.class.isAssignableFrom(type) && !StringUtils.hasText(pathVariable.value());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Optional<Object> resolveArgumentValue(MethodParameter methodParameter,
|
||||
BindingContext context, ServerWebExchange exchange) {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import java.util.Optional;
|
|||
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
|
@ -52,21 +53,26 @@ import org.springframework.web.server.ServerWebExchange;
|
|||
public class PathVariableMethodArgumentResolver extends AbstractNamedValueSyncArgumentResolver {
|
||||
|
||||
|
||||
public PathVariableMethodArgumentResolver(ConfigurableBeanFactory beanFactory) {
|
||||
super(beanFactory);
|
||||
/**
|
||||
* @param beanFactory a bean factory to use for resolving ${...}
|
||||
* placeholder and #{...} SpEL expressions in default values;
|
||||
* or {@code null} if default values are not expected to contain expressions
|
||||
* @param adapterRegistry for checking reactive type wrappers
|
||||
*/
|
||||
public PathVariableMethodArgumentResolver(ConfigurableBeanFactory beanFactory,
|
||||
ReactiveAdapterRegistry adapterRegistry) {
|
||||
|
||||
super(beanFactory, adapterRegistry);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
if (!parameter.hasParameterAnnotation(PathVariable.class)) {
|
||||
return false;
|
||||
}
|
||||
if (Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType())) {
|
||||
String paramName = parameter.getParameterAnnotation(PathVariable.class).value();
|
||||
return StringUtils.hasText(paramName);
|
||||
}
|
||||
return true;
|
||||
return checkAnnotatedParamNoReactiveWrapper(parameter, PathVariable.class, this::singlePathVariable);
|
||||
}
|
||||
|
||||
private boolean singlePathVariable(PathVariable pathVariable, Class<?> type) {
|
||||
return !Map.class.isAssignableFrom(type) || StringUtils.hasText(pathVariable.name());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -21,8 +21,11 @@ import java.security.Principal;
|
|||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.reactive.BindingContext;
|
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolverSupport;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
/**
|
||||
|
|
@ -32,26 +35,26 @@ import org.springframework.web.server.ServerWebExchange;
|
|||
* @since 5.0
|
||||
* @see ServerWebExchangeArgumentResolver
|
||||
*/
|
||||
public class PrincipalArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
public class PrincipalArgumentResolver extends HandlerMethodArgumentResolverSupport
|
||||
implements HandlerMethodArgumentResolver {
|
||||
|
||||
|
||||
public PrincipalArgumentResolver(ReactiveAdapterRegistry adapterRegistry) {
|
||||
super(adapterRegistry);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return (Principal.class.isAssignableFrom(parameter.getParameterType()));
|
||||
return checkParamTypeNoReactiveWrapper(parameter, Principal.class::isAssignableFrom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Object> resolveArgument(MethodParameter parameter, BindingContext context,
|
||||
ServerWebExchange exchange) {
|
||||
|
||||
Class<?> paramType = parameter.getParameterType();
|
||||
if (Principal.class.isAssignableFrom(paramType)) {
|
||||
return exchange.getPrincipal().cast(Object.class);
|
||||
}
|
||||
else {
|
||||
// should never happen...
|
||||
throw new IllegalArgumentException(
|
||||
"Unknown parameter type: " + paramType + " in method: " + parameter.getMethod());
|
||||
}
|
||||
Assert.isAssignable(Principal.class, parameter.getParameterType());
|
||||
return exchange.getPrincipal().cast(Object.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import java.util.Optional;
|
|||
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
import org.springframework.web.bind.annotation.ValueConstants;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
|
@ -34,14 +35,22 @@ import org.springframework.web.server.ServerWebInputException;
|
|||
public class RequestAttributeMethodArgumentResolver extends AbstractNamedValueSyncArgumentResolver {
|
||||
|
||||
|
||||
public RequestAttributeMethodArgumentResolver(ConfigurableBeanFactory beanFactory) {
|
||||
super(beanFactory);
|
||||
/**
|
||||
* @param beanFactory a bean factory to use for resolving ${...}
|
||||
* placeholder and #{...} SpEL expressions in default values;
|
||||
* or {@code null} if default values are not expected to have expressions
|
||||
* @param adapterRegistry for checking reactive type wrappers
|
||||
*/
|
||||
public RequestAttributeMethodArgumentResolver(ConfigurableBeanFactory beanFactory,
|
||||
ReactiveAdapterRegistry adapterRegistry) {
|
||||
|
||||
super(beanFactory, adapterRegistry);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return parameter.hasParameterAnnotation(RequestAttribute.class);
|
||||
public boolean supportsParameter(MethodParameter param) {
|
||||
return checkAnnotatedParamNoReactiveWrapper(param, RequestAttribute.class, (annot, type) -> true);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -47,19 +47,7 @@ import org.springframework.web.server.ServerWebInputException;
|
|||
public class RequestBodyArgumentResolver extends AbstractMessageReaderArgumentResolver
|
||||
implements HandlerMethodArgumentResolver {
|
||||
|
||||
/**
|
||||
* Constructor with {@link HttpMessageReader}'s and a {@link Validator}.
|
||||
* @param readers readers for de-serializing the request body with
|
||||
*/
|
||||
public RequestBodyArgumentResolver(List<HttpMessageReader<?>> readers) {
|
||||
super(readers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that also accepts a {@link ReactiveAdapterRegistry}.
|
||||
* @param readers readers for de-serializing the request body with
|
||||
* @param registry for adapting to other reactive types from Flux and Mono
|
||||
*/
|
||||
public RequestBodyArgumentResolver(List<HttpMessageReader<?>> readers, ReactiveAdapterRegistry registry) {
|
||||
super(readers, registry);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,10 +20,12 @@ import java.util.Map;
|
|||
import java.util.Optional;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.reactive.BindingContext;
|
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolverSupport;
|
||||
import org.springframework.web.reactive.result.method.SyncHandlerMethodArgumentResolver;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
|
|
@ -40,15 +42,25 @@ import org.springframework.web.server.ServerWebExchange;
|
|||
* @since 5.0
|
||||
* @see RequestHeaderMethodArgumentResolver
|
||||
*/
|
||||
public class RequestHeaderMapMethodArgumentResolver implements SyncHandlerMethodArgumentResolver {
|
||||
public class RequestHeaderMapMethodArgumentResolver extends HandlerMethodArgumentResolverSupport
|
||||
implements SyncHandlerMethodArgumentResolver {
|
||||
|
||||
|
||||
public RequestHeaderMapMethodArgumentResolver(ReactiveAdapterRegistry adapterRegistry) {
|
||||
super(adapterRegistry);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return (parameter.hasParameterAnnotation(RequestHeader.class) &&
|
||||
Map.class.isAssignableFrom(parameter.getParameterType()));
|
||||
public boolean supportsParameter(MethodParameter param) {
|
||||
return checkAnnotatedParamNoReactiveWrapper(param, RequestHeader.class, this::allParams);
|
||||
}
|
||||
|
||||
private boolean allParams(RequestHeader annotation, Class<?> type) {
|
||||
return Map.class.isAssignableFrom(type);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Optional<Object> resolveArgumentValue(MethodParameter methodParameter,
|
||||
BindingContext context, ServerWebExchange exchange) {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import java.util.Optional;
|
|||
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
|
@ -49,16 +50,22 @@ public class RequestHeaderMethodArgumentResolver extends AbstractNamedValueSyncA
|
|||
* @param beanFactory a bean factory to use for resolving ${...}
|
||||
* placeholder and #{...} SpEL expressions in default values;
|
||||
* or {@code null} if default values are not expected to have expressions
|
||||
* @param adapterRegistry for checking reactive type wrappers
|
||||
*/
|
||||
public RequestHeaderMethodArgumentResolver(ConfigurableBeanFactory beanFactory) {
|
||||
super(beanFactory);
|
||||
public RequestHeaderMethodArgumentResolver(ConfigurableBeanFactory beanFactory,
|
||||
ReactiveAdapterRegistry adapterRegistry) {
|
||||
|
||||
super(beanFactory, adapterRegistry);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return (parameter.hasParameterAnnotation(RequestHeader.class) &&
|
||||
!Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType()));
|
||||
public boolean supportsParameter(MethodParameter param) {
|
||||
return checkAnnotatedParamNoReactiveWrapper(param, RequestHeader.class, this::singleParam);
|
||||
}
|
||||
|
||||
private boolean singleParam(RequestHeader annotation, Class<?> type) {
|
||||
return !Map.class.isAssignableFrom(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -294,26 +294,26 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, Application
|
|||
List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();
|
||||
|
||||
// Annotation-based argument resolution
|
||||
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory()));
|
||||
resolvers.add(new RequestParamMapMethodArgumentResolver());
|
||||
resolvers.add(new PathVariableMethodArgumentResolver(getBeanFactory()));
|
||||
resolvers.add(new PathVariableMapMethodArgumentResolver());
|
||||
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), getReactiveAdapterRegistry(), false));
|
||||
resolvers.add(new RequestParamMapMethodArgumentResolver(getReactiveAdapterRegistry()));
|
||||
resolvers.add(new PathVariableMethodArgumentResolver(getBeanFactory(), getReactiveAdapterRegistry()));
|
||||
resolvers.add(new PathVariableMapMethodArgumentResolver(getReactiveAdapterRegistry()));
|
||||
resolvers.add(new RequestBodyArgumentResolver(getMessageReaders(), getReactiveAdapterRegistry()));
|
||||
resolvers.add(new ModelAttributeMethodArgumentResolver(getReactiveAdapterRegistry()));
|
||||
resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
|
||||
resolvers.add(new RequestHeaderMapMethodArgumentResolver());
|
||||
resolvers.add(new CookieValueMethodArgumentResolver(getBeanFactory()));
|
||||
resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
|
||||
resolvers.add(new SessionAttributeMethodArgumentResolver(getBeanFactory()));
|
||||
resolvers.add(new RequestAttributeMethodArgumentResolver(getBeanFactory()));
|
||||
resolvers.add(new ModelAttributeMethodArgumentResolver(getReactiveAdapterRegistry(), false));
|
||||
resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory(), getReactiveAdapterRegistry()));
|
||||
resolvers.add(new RequestHeaderMapMethodArgumentResolver(getReactiveAdapterRegistry()));
|
||||
resolvers.add(new CookieValueMethodArgumentResolver(getBeanFactory(), getReactiveAdapterRegistry()));
|
||||
resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory(), getReactiveAdapterRegistry()));
|
||||
resolvers.add(new SessionAttributeMethodArgumentResolver(getBeanFactory(), getReactiveAdapterRegistry()));
|
||||
resolvers.add(new RequestAttributeMethodArgumentResolver(getBeanFactory(), getReactiveAdapterRegistry()));
|
||||
|
||||
// Type-based argument resolution
|
||||
resolvers.add(new HttpEntityArgumentResolver(getMessageReaders(), getReactiveAdapterRegistry()));
|
||||
resolvers.add(new ModelArgumentResolver());
|
||||
resolvers.add(new ModelArgumentResolver(getReactiveAdapterRegistry()));
|
||||
resolvers.add(new ErrorsMethodArgumentResolver(getReactiveAdapterRegistry()));
|
||||
resolvers.add(new ServerWebExchangeArgumentResolver());
|
||||
resolvers.add(new PrincipalArgumentResolver());
|
||||
resolvers.add(new WebSessionArgumentResolver());
|
||||
resolvers.add(new ServerWebExchangeArgumentResolver(getReactiveAdapterRegistry()));
|
||||
resolvers.add(new PrincipalArgumentResolver(getReactiveAdapterRegistry()));
|
||||
resolvers.add(new WebSessionArgumentResolver(getReactiveAdapterRegistry()));
|
||||
|
||||
// Custom resolvers
|
||||
if (getCustomArgumentResolvers() != null) {
|
||||
|
|
@ -321,7 +321,7 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, Application
|
|||
}
|
||||
|
||||
// Catch-all
|
||||
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
|
||||
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), getReactiveAdapterRegistry(), true));
|
||||
resolvers.add(new ModelAttributeMethodArgumentResolver(getReactiveAdapterRegistry(), true));
|
||||
return resolvers;
|
||||
}
|
||||
|
|
@ -330,19 +330,19 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, Application
|
|||
List<SyncHandlerMethodArgumentResolver> resolvers = new ArrayList<>();
|
||||
|
||||
// Annotation-based argument resolution
|
||||
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
|
||||
resolvers.add(new RequestParamMapMethodArgumentResolver());
|
||||
resolvers.add(new PathVariableMethodArgumentResolver(getBeanFactory()));
|
||||
resolvers.add(new PathVariableMapMethodArgumentResolver());
|
||||
resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
|
||||
resolvers.add(new RequestHeaderMapMethodArgumentResolver());
|
||||
resolvers.add(new CookieValueMethodArgumentResolver(getBeanFactory()));
|
||||
resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
|
||||
resolvers.add(new RequestAttributeMethodArgumentResolver(getBeanFactory()));
|
||||
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), getReactiveAdapterRegistry(), false));
|
||||
resolvers.add(new RequestParamMapMethodArgumentResolver(getReactiveAdapterRegistry()));
|
||||
resolvers.add(new PathVariableMethodArgumentResolver(getBeanFactory(), getReactiveAdapterRegistry()));
|
||||
resolvers.add(new PathVariableMapMethodArgumentResolver(getReactiveAdapterRegistry()));
|
||||
resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory(), getReactiveAdapterRegistry()));
|
||||
resolvers.add(new RequestHeaderMapMethodArgumentResolver(getReactiveAdapterRegistry()));
|
||||
resolvers.add(new CookieValueMethodArgumentResolver(getBeanFactory(), getReactiveAdapterRegistry()));
|
||||
resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory(), getReactiveAdapterRegistry()));
|
||||
resolvers.add(new RequestAttributeMethodArgumentResolver(getBeanFactory(), getReactiveAdapterRegistry()));
|
||||
|
||||
// Type-based argument resolution
|
||||
resolvers.add(new ModelArgumentResolver());
|
||||
resolvers.add(new ServerWebExchangeArgumentResolver());
|
||||
resolvers.add(new ModelArgumentResolver(getReactiveAdapterRegistry()));
|
||||
resolvers.add(new ServerWebExchangeArgumentResolver(getReactiveAdapterRegistry()));
|
||||
|
||||
// Custom resolvers
|
||||
if (getCustomInitBinderArgumentResolvers() != null) {
|
||||
|
|
@ -350,7 +350,7 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, Application
|
|||
}
|
||||
|
||||
// Catch-all
|
||||
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
|
||||
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), getReactiveAdapterRegistry(), true));
|
||||
return resolvers;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,11 +20,13 @@ import java.util.Map;
|
|||
import java.util.Optional;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.reactive.BindingContext;
|
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolverSupport;
|
||||
import org.springframework.web.reactive.result.method.SyncHandlerMethodArgumentResolver;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
|
|
@ -43,20 +45,25 @@ import org.springframework.web.server.ServerWebExchange;
|
|||
* @since 5.0
|
||||
* @see RequestParamMethodArgumentResolver
|
||||
*/
|
||||
public class RequestParamMapMethodArgumentResolver implements SyncHandlerMethodArgumentResolver {
|
||||
public class RequestParamMapMethodArgumentResolver extends HandlerMethodArgumentResolverSupport
|
||||
implements SyncHandlerMethodArgumentResolver {
|
||||
|
||||
|
||||
public RequestParamMapMethodArgumentResolver(ReactiveAdapterRegistry adapterRegistry) {
|
||||
super(adapterRegistry);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter methodParam) {
|
||||
RequestParam requestParam = methodParam.getParameterAnnotation(RequestParam.class);
|
||||
if (requestParam != null) {
|
||||
if (Map.class.isAssignableFrom(methodParam.getParameterType())) {
|
||||
return !StringUtils.hasText(requestParam.name());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
public boolean supportsParameter(MethodParameter param) {
|
||||
return checkAnnotatedParamNoReactiveWrapper(param, RequestParam.class, this::allParams);
|
||||
}
|
||||
|
||||
private boolean allParams(RequestParam requestParam, Class<?> type) {
|
||||
return Map.class.isAssignableFrom(type) && !StringUtils.hasText(requestParam.name());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Optional<Object> resolveArgumentValue(MethodParameter methodParameter,
|
||||
BindingContext context, ServerWebExchange exchange) {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import java.util.Optional;
|
|||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
|
@ -56,46 +57,38 @@ public class RequestParamMethodArgumentResolver extends AbstractNamedValueSyncAr
|
|||
private final boolean useDefaultResolution;
|
||||
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
* @param beanFactory a bean factory used for resolving ${...} placeholder
|
||||
* and #{...} SpEL expressions in default values, or {@code null} if default
|
||||
* values are not expected to contain expressions
|
||||
*/
|
||||
public RequestParamMethodArgumentResolver(ConfigurableBeanFactory beanFactory) {
|
||||
this(beanFactory, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor with a default resolution mode flag.
|
||||
* @param beanFactory a bean factory used for resolving ${...} placeholder
|
||||
* and #{...} SpEL expressions in default values, or {@code null} if default
|
||||
* values are not expected to contain expressions
|
||||
* @param adapterRegistry for checking reactive type wrappers
|
||||
* @param useDefaultResolution in default resolution mode a method argument
|
||||
* that is a simple type, as defined in {@link BeanUtils#isSimpleProperty},
|
||||
* is treated as a request parameter even if it isn't annotated, the
|
||||
* request parameter name is derived from the method parameter name.
|
||||
*/
|
||||
public RequestParamMethodArgumentResolver(ConfigurableBeanFactory beanFactory,
|
||||
boolean useDefaultResolution) {
|
||||
ReactiveAdapterRegistry adapterRegistry, boolean useDefaultResolution) {
|
||||
|
||||
super(beanFactory);
|
||||
super(beanFactory, adapterRegistry);
|
||||
this.useDefaultResolution = useDefaultResolution;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
if (parameter.hasParameterAnnotation(RequestParam.class)) {
|
||||
if (Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType())) {
|
||||
String paramName = parameter.getParameterAnnotation(RequestParam.class).name();
|
||||
return StringUtils.hasText(paramName);
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
public boolean supportsParameter(MethodParameter param) {
|
||||
if (checkAnnotatedParamNoReactiveWrapper(param, RequestParam.class, this::singleParam)) {
|
||||
return true;
|
||||
}
|
||||
return (this.useDefaultResolution && BeanUtils.isSimpleProperty(parameter.getNestedParameterType()));
|
||||
else if (this.useDefaultResolution) {
|
||||
return checkParamTypeNoReactiveWrapper(param, BeanUtils::isSimpleProperty);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean singleParam(RequestParam requestParam, Class<?> type) {
|
||||
return !Map.class.isAssignableFrom(type) || StringUtils.hasText(requestParam.name());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -132,11 +125,11 @@ public class RequestParamMethodArgumentResolver extends AbstractNamedValueSyncAr
|
|||
|
||||
private static class RequestParamNamedValueInfo extends NamedValueInfo {
|
||||
|
||||
public RequestParamNamedValueInfo() {
|
||||
RequestParamNamedValueInfo() {
|
||||
super("", false, ValueConstants.DEFAULT_NONE);
|
||||
}
|
||||
|
||||
public RequestParamNamedValueInfo(RequestParam annotation) {
|
||||
RequestParamNamedValueInfo(RequestParam annotation) {
|
||||
super(annotation.name(), annotation.required(), annotation.defaultValue());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,10 +19,12 @@ 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;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.web.reactive.BindingContext;
|
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolverSupport;
|
||||
import org.springframework.web.reactive.result.method.SyncHandlerMethodArgumentResolver;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
|
|
@ -43,16 +45,22 @@ import org.springframework.web.server.ServerWebExchange;
|
|||
* @see WebSessionArgumentResolver
|
||||
* @see PrincipalArgumentResolver
|
||||
*/
|
||||
public class ServerWebExchangeArgumentResolver implements SyncHandlerMethodArgumentResolver {
|
||||
public class ServerWebExchangeArgumentResolver extends HandlerMethodArgumentResolverSupport
|
||||
implements SyncHandlerMethodArgumentResolver {
|
||||
|
||||
|
||||
public ServerWebExchangeArgumentResolver(ReactiveAdapterRegistry adapterRegistry) {
|
||||
super(adapterRegistry);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
Class<?> paramType = parameter.getParameterType();
|
||||
return (ServerWebExchange.class.isAssignableFrom(paramType) ||
|
||||
ServerHttpRequest.class.isAssignableFrom(paramType) ||
|
||||
ServerHttpResponse.class.isAssignableFrom(paramType) ||
|
||||
HttpMethod.class == paramType);
|
||||
return checkParamTypeNoReactiveWrapper(parameter,
|
||||
type -> ServerWebExchange.class.isAssignableFrom(type) ||
|
||||
ServerHttpRequest.class.isAssignableFrom(type) ||
|
||||
ServerHttpResponse.class.isAssignableFrom(type) ||
|
||||
HttpMethod.class == type);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import reactor.core.publisher.Mono;
|
|||
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.web.bind.annotation.SessionAttribute;
|
||||
import org.springframework.web.bind.annotation.ValueConstants;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
|
@ -36,8 +37,10 @@ import org.springframework.web.server.ServerWebInputException;
|
|||
public class SessionAttributeMethodArgumentResolver extends AbstractNamedValueArgumentResolver {
|
||||
|
||||
|
||||
public SessionAttributeMethodArgumentResolver(ConfigurableBeanFactory beanFactory) {
|
||||
super(beanFactory);
|
||||
public SessionAttributeMethodArgumentResolver(ConfigurableBeanFactory beanFactory,
|
||||
ReactiveAdapterRegistry adapterRegistry) {
|
||||
|
||||
super(beanFactory, adapterRegistry);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -19,8 +19,11 @@ package org.springframework.web.reactive.result.method.annotation;
|
|||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.reactive.BindingContext;
|
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolverSupport;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebSession;
|
||||
|
||||
|
|
@ -31,26 +34,26 @@ import org.springframework.web.server.WebSession;
|
|||
* @since 5.0
|
||||
* @see ServerWebExchangeArgumentResolver
|
||||
*/
|
||||
public class WebSessionArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
public class WebSessionArgumentResolver extends HandlerMethodArgumentResolverSupport
|
||||
implements HandlerMethodArgumentResolver {
|
||||
|
||||
|
||||
public WebSessionArgumentResolver(ReactiveAdapterRegistry adapterRegistry) {
|
||||
super(adapterRegistry);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return (WebSession.class.isAssignableFrom(parameter.getParameterType()));
|
||||
return checkParamTypeNoReactiveWrapper(parameter, WebSession.class::isAssignableFrom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Object> resolveArgument(MethodParameter parameter, BindingContext context,
|
||||
ServerWebExchange exchange) {
|
||||
|
||||
Class<?> paramType = parameter.getParameterType();
|
||||
if (WebSession.class.isAssignableFrom(paramType)) {
|
||||
return exchange.getSession().cast(Object.class);
|
||||
}
|
||||
else {
|
||||
// should never happen...
|
||||
throw new IllegalArgumentException(
|
||||
"Unknown parameter type: " + paramType + " in method: " + parameter.getMethod());
|
||||
}
|
||||
Assert.isAssignable(WebSession.class, parameter.getParameterType());
|
||||
return exchange.getSession().cast(Object.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,11 +25,13 @@ import reactor.test.StepVerifier;
|
|||
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.core.annotation.SynthesizingMethodParameter;
|
||||
import org.springframework.http.HttpCookie;
|
||||
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.util.ReflectionUtils;
|
||||
import org.springframework.web.bind.annotation.CookieValue;
|
||||
import org.springframework.web.reactive.BindingContext;
|
||||
import org.springframework.web.server.ServerWebInputException;
|
||||
|
|
@ -53,6 +55,7 @@ public class CookieValueMethodArgumentResolverTests {
|
|||
private MethodParameter cookieParameter;
|
||||
private MethodParameter cookieStringParameter;
|
||||
private MethodParameter stringParameter;
|
||||
private MethodParameter cookieMonoParameter;
|
||||
|
||||
|
||||
@Before
|
||||
|
|
@ -60,14 +63,16 @@ public class CookieValueMethodArgumentResolverTests {
|
|||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
context.refresh();
|
||||
|
||||
this.resolver = new CookieValueMethodArgumentResolver(context.getBeanFactory());
|
||||
ReactiveAdapterRegistry adapterRegistry = new ReactiveAdapterRegistry();
|
||||
this.resolver = new CookieValueMethodArgumentResolver(context.getBeanFactory(), adapterRegistry);
|
||||
this.request = MockServerHttpRequest.get("/").build();
|
||||
this.bindingContext = new BindingContext();
|
||||
|
||||
Method method = getClass().getMethod("params", HttpCookie.class, String.class, String.class);
|
||||
Method method = ReflectionUtils.findMethod(getClass(), "params", (Class<?>[]) null);
|
||||
this.cookieParameter = new SynthesizingMethodParameter(method, 0);
|
||||
this.cookieStringParameter = new SynthesizingMethodParameter(method, 1);
|
||||
this.stringParameter = new SynthesizingMethodParameter(method, 2);
|
||||
this.cookieMonoParameter = new SynthesizingMethodParameter(method, 3);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -75,7 +80,20 @@ public class CookieValueMethodArgumentResolverTests {
|
|||
public void supportsParameter() {
|
||||
assertTrue(this.resolver.supportsParameter(this.cookieParameter));
|
||||
assertTrue(this.resolver.supportsParameter(this.cookieStringParameter));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesNotSupportParameter() {
|
||||
assertFalse(this.resolver.supportsParameter(this.stringParameter));
|
||||
try {
|
||||
this.resolver.supportsParameter(this.cookieMonoParameter);
|
||||
fail();
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
assertTrue("Unexpected error message:\n" + ex.getMessage(),
|
||||
ex.getMessage().startsWith(
|
||||
"CookieValueMethodArgumentResolver doesn't support reactive type wrapper"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -128,7 +146,8 @@ public class CookieValueMethodArgumentResolverTests {
|
|||
public void params(
|
||||
@CookieValue("name") HttpCookie cookie,
|
||||
@CookieValue(name = "name", defaultValue = "bar") String cookieString,
|
||||
String stringParam) {
|
||||
String stringParam,
|
||||
@CookieValue Mono<String> monoCookie) {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import org.springframework.web.server.adapter.DefaultServerWebExchange;
|
|||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ErrorsMethodArgumentResolver}.
|
||||
|
|
@ -78,12 +79,24 @@ public class ErrorsArgumentResolverTests {
|
|||
|
||||
parameter = this.testMethod.arg(BindingResult.class);
|
||||
assertTrue(this.resolver.supportsParameter(parameter));
|
||||
}
|
||||
|
||||
parameter = this.testMethod.arg(ResolvableType.forClassWithGenerics(Mono.class, Errors.class));
|
||||
@Test
|
||||
public void doesNotSupport() throws Exception {
|
||||
|
||||
MethodParameter parameter = this.testMethod.arg(String.class);
|
||||
assertFalse(this.resolver.supportsParameter(parameter));
|
||||
|
||||
parameter = this.testMethod.arg(String.class);
|
||||
assertFalse(this.resolver.supportsParameter(parameter));
|
||||
try {
|
||||
parameter = this.testMethod.arg(ResolvableType.forClassWithGenerics(Mono.class, Errors.class));
|
||||
assertFalse(this.resolver.supportsParameter(parameter));
|
||||
fail();
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
assertTrue("Unexpected error message:\n" + ex.getMessage(),
|
||||
ex.getMessage().startsWith(
|
||||
"ErrorsMethodArgumentResolver doesn't support reactive type wrapper"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -25,9 +25,11 @@ import reactor.core.publisher.Mono;
|
|||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
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.util.ReflectionUtils;
|
||||
import org.springframework.web.reactive.BindingContext;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.adapter.DefaultServerWebExchange;
|
||||
|
|
@ -47,27 +49,43 @@ public class ExpressionValueMethodArgumentResolverTests {
|
|||
|
||||
private MethodParameter paramSystemProperty;
|
||||
private MethodParameter paramNotSupported;
|
||||
private MethodParameter paramAlsoNotSupported;
|
||||
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
context.refresh();
|
||||
this.resolver = new ExpressionValueMethodArgumentResolver(context.getBeanFactory());
|
||||
ReactiveAdapterRegistry adapterRegistry = new ReactiveAdapterRegistry();
|
||||
this.resolver = new ExpressionValueMethodArgumentResolver(context.getBeanFactory(), adapterRegistry);
|
||||
|
||||
ServerHttpRequest request = MockServerHttpRequest.get("/").build();
|
||||
this.exchange = new DefaultServerWebExchange(request, new MockServerHttpResponse());
|
||||
|
||||
Method method = getClass().getMethod("params", int.class, String.class);
|
||||
Method method = ReflectionUtils.findMethod(getClass(), "params", (Class<?>[]) null);
|
||||
this.paramSystemProperty = new MethodParameter(method, 0);
|
||||
this.paramNotSupported = new MethodParameter(method, 1);
|
||||
this.paramAlsoNotSupported = new MethodParameter(method, 2);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void supportsParameter() throws Exception {
|
||||
assertTrue(this.resolver.supportsParameter(this.paramSystemProperty));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesNotSupport() throws Exception {
|
||||
assertFalse(this.resolver.supportsParameter(this.paramNotSupported));
|
||||
try {
|
||||
this.resolver.supportsParameter(this.paramAlsoNotSupported);
|
||||
fail();
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
assertTrue("Unexpected error message:\n" + ex.getMessage(),
|
||||
ex.getMessage().startsWith(
|
||||
"ExpressionValueMethodArgumentResolver doesn't support reactive type wrapper"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -90,7 +108,10 @@ public class ExpressionValueMethodArgumentResolverTests {
|
|||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void params(@Value("#{systemProperties.systemProperty}") int param1, String notSupported) {
|
||||
public void params(
|
||||
@Value("#{systemProperties.systemProperty}") int param1,
|
||||
String notSupported,
|
||||
@Value("#{systemProperties.foo}") Mono<String> alsoNotSupported) {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import rx.RxReactiveStreams;
|
|||
import rx.Single;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.codec.StringDecoder;
|
||||
import org.springframework.http.HttpEntity;
|
||||
|
|
@ -44,14 +45,19 @@ 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.util.ObjectUtils;
|
||||
import org.springframework.web.reactive.BindingContext;
|
||||
import org.springframework.web.method.ResolvableMethod;
|
||||
import org.springframework.web.reactive.BindingContext;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.ServerWebInputException;
|
||||
import org.springframework.web.server.adapter.DefaultServerWebExchange;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.core.ResolvableType.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.springframework.core.ResolvableType.forClassWithGenerics;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link HttpEntityArgumentResolver}.When adding a test also
|
||||
|
|
@ -78,7 +84,7 @@ public class HttpEntityArgumentResolverTests {
|
|||
private HttpEntityArgumentResolver createResolver() {
|
||||
List<HttpMessageReader<?>> readers = new ArrayList<>();
|
||||
readers.add(new DecoderHttpMessageReader<>(new StringDecoder()));
|
||||
return new HttpEntityArgumentResolver(readers);
|
||||
return new HttpEntityArgumentResolver(readers, new ReactiveAdapterRegistry());
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -105,6 +111,15 @@ public class HttpEntityArgumentResolverTests {
|
|||
public void doesNotSupport() throws Exception {
|
||||
assertFalse(this.resolver.supportsParameter(this.testMethod.arg(Mono.class, String.class)));
|
||||
assertFalse(this.resolver.supportsParameter(this.testMethod.arg(String.class)));
|
||||
try {
|
||||
this.resolver.supportsParameter(this.testMethod.arg(Mono.class, httpEntityType(String.class)));
|
||||
fail();
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
assertTrue("Unexpected error message:\n" + ex.getMessage(),
|
||||
ex.getMessage().startsWith(
|
||||
"HttpEntityArgumentResolver doesn't support reactive type wrapper"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -348,6 +363,7 @@ public class HttpEntityArgumentResolverTests {
|
|||
HttpEntity<io.reactivex.Observable<String>> rxJava2ObservableBody,
|
||||
HttpEntity<Flowable<String>> flowableBody,
|
||||
HttpEntity<CompletableFuture<String>> completableFutureBody,
|
||||
RequestEntity<String> requestEntity) {}
|
||||
RequestEntity<String> requestEntity,
|
||||
Mono<HttpEntity<String>> httpEntityMono) {}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import org.junit.Before;
|
|||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
|
|
@ -112,7 +113,8 @@ public class InitBinderBindingContextTests {
|
|||
@Test
|
||||
public void createBinderTypeConversion() throws Exception {
|
||||
this.request = MockServerHttpRequest.get("/path?requestParam=22").build();
|
||||
this.argumentResolvers.add(new RequestParamMethodArgumentResolver(null, false));
|
||||
ReactiveAdapterRegistry adapterRegistry = new ReactiveAdapterRegistry();
|
||||
this.argumentResolvers.add(new RequestParamMethodArgumentResolver(null, adapterRegistry, false));
|
||||
|
||||
BindingContext context = createBindingContext("initBinderTypeConversion", WebDataBinder.class, int.class);
|
||||
WebDataBinder dataBinder = context.createDataBinder(createExchange(), null, "foo");
|
||||
|
|
|
|||
|
|
@ -281,7 +281,7 @@ public class ModelAttributeMethodArgumentResolverTests {
|
|||
|
||||
|
||||
private ModelAttributeMethodArgumentResolver createResolver() {
|
||||
return new ModelAttributeMethodArgumentResolver(new ReactiveAdapterRegistry());
|
||||
return new ModelAttributeMethodArgumentResolver(new ReactiveAdapterRegistry(), false);
|
||||
}
|
||||
|
||||
private ServerWebExchange exchange(String formData) throws URISyntaxException {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package org.springframework.web.reactive.result.method.annotation;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -120,14 +121,17 @@ public class ModelInitializerTests {
|
|||
private List<InvocableHandlerMethod> getAttributeMethods(Object controller) {
|
||||
return MethodIntrospector
|
||||
.selectMethods(controller.getClass(), ATTRIBUTE_METHODS).stream()
|
||||
.map(method -> {
|
||||
InvocableHandlerMethod invocable = new InvocableHandlerMethod(controller, method);
|
||||
invocable.setArgumentResolvers(Collections.singletonList(new ModelArgumentResolver()));
|
||||
return invocable;
|
||||
})
|
||||
.map(method -> toInvocable(controller, method))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private InvocableHandlerMethod toInvocable(Object controller, Method method) {
|
||||
ModelArgumentResolver resolver = new ModelArgumentResolver(new ReactiveAdapterRegistry());
|
||||
InvocableHandlerMethod handlerMethod = new InvocableHandlerMethod(controller, method);
|
||||
handlerMethod.setArgumentResolvers(Collections.singletonList(resolver));
|
||||
return handlerMethod;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class TestController {
|
||||
|
|
|
|||
|
|
@ -26,9 +26,11 @@ import org.junit.Test;
|
|||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
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.util.ReflectionUtils;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.reactive.BindingContext;
|
||||
import org.springframework.web.reactive.HandlerMapping;
|
||||
|
|
@ -38,6 +40,7 @@ import org.springframework.web.server.adapter.DefaultServerWebExchange;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link PathVariableMapMethodArgumentResolver}.
|
||||
|
|
@ -53,19 +56,21 @@ public class PathVariableMapMethodArgumentResolverTests {
|
|||
private MethodParameter paramMap;
|
||||
private MethodParameter paramNamedMap;
|
||||
private MethodParameter paramMapNoAnnot;
|
||||
private MethodParameter paramMonoMap;
|
||||
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
this.resolver = new PathVariableMapMethodArgumentResolver();
|
||||
this.resolver = new PathVariableMapMethodArgumentResolver(new ReactiveAdapterRegistry());
|
||||
|
||||
ServerHttpRequest request = MockServerHttpRequest.get("/").build();
|
||||
this.exchange = new DefaultServerWebExchange(request, new MockServerHttpResponse());
|
||||
|
||||
Method method = getClass().getMethod("handle", Map.class, Map.class, Map.class);
|
||||
Method method = ReflectionUtils.findMethod(getClass(), "handle", (Class<?>[]) null);
|
||||
this.paramMap = new MethodParameter(method, 0);
|
||||
this.paramNamedMap = new MethodParameter(method, 1);
|
||||
this.paramMapNoAnnot = new MethodParameter(method, 2);
|
||||
this.paramMonoMap = new MethodParameter(method, 3);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -74,6 +79,15 @@ public class PathVariableMapMethodArgumentResolverTests {
|
|||
assertTrue(resolver.supportsParameter(paramMap));
|
||||
assertFalse(resolver.supportsParameter(paramNamedMap));
|
||||
assertFalse(resolver.supportsParameter(paramMapNoAnnot));
|
||||
try {
|
||||
this.resolver.supportsParameter(this.paramMonoMap);
|
||||
fail();
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
assertTrue("Unexpected error message:\n" + ex.getMessage(),
|
||||
ex.getMessage().startsWith(
|
||||
"PathVariableMapMethodArgumentResolver doesn't support reactive type wrapper"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -102,7 +116,8 @@ public class PathVariableMapMethodArgumentResolverTests {
|
|||
public void handle(
|
||||
@PathVariable Map<String, String> map,
|
||||
@PathVariable(value = "name") Map<String, String> namedMap,
|
||||
Map<String, String> mapWithoutAnnotat) {
|
||||
Map<String, String> mapWithoutAnnotat,
|
||||
@PathVariable Mono<Map<?, ?>> monoMap) {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import reactor.core.publisher.Mono;
|
|||
import reactor.test.StepVerifier;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.core.annotation.SynthesizingMethodParameter;
|
||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
|
|
@ -44,6 +45,7 @@ import org.springframework.web.server.adapter.DefaultServerWebExchange;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link PathVariableMethodArgumentResolver}.
|
||||
|
|
@ -58,17 +60,15 @@ public class PathVariableMethodArgumentResolverTests {
|
|||
private ServerWebExchange exchange;
|
||||
|
||||
private MethodParameter paramNamedString;
|
||||
|
||||
private MethodParameter paramString;
|
||||
|
||||
private MethodParameter paramNotRequired;
|
||||
|
||||
private MethodParameter paramOptional;
|
||||
private MethodParameter paramMono;
|
||||
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
this.resolver = new PathVariableMethodArgumentResolver(null);
|
||||
this.resolver = new PathVariableMethodArgumentResolver(null, new ReactiveAdapterRegistry());
|
||||
|
||||
ServerHttpRequest request = MockServerHttpRequest.get("/").build();
|
||||
this.exchange = new DefaultServerWebExchange(request, new MockServerHttpResponse());
|
||||
|
|
@ -78,6 +78,7 @@ public class PathVariableMethodArgumentResolverTests {
|
|||
paramString = new SynthesizingMethodParameter(method, 1);
|
||||
paramNotRequired = new SynthesizingMethodParameter(method, 2);
|
||||
paramOptional = new SynthesizingMethodParameter(method, 3);
|
||||
paramMono = new SynthesizingMethodParameter(method, 4);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -85,6 +86,15 @@ public class PathVariableMethodArgumentResolverTests {
|
|||
public void supportsParameter() {
|
||||
assertTrue(this.resolver.supportsParameter(this.paramNamedString));
|
||||
assertFalse(this.resolver.supportsParameter(this.paramString));
|
||||
try {
|
||||
this.resolver.supportsParameter(this.paramMono);
|
||||
fail();
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
assertTrue("Unexpected error message:\n" + ex.getMessage(),
|
||||
ex.getMessage().startsWith(
|
||||
"PathVariableMethodArgumentResolver doesn't support reactive type wrapper"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -161,10 +171,13 @@ public class PathVariableMethodArgumentResolverTests {
|
|||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void handle(@PathVariable(value = "name") String param1, String param2,
|
||||
@SuppressWarnings({"unused", "OptionalUsedAsFieldOrParameterType"})
|
||||
public void handle(
|
||||
@PathVariable(value = "name") String param1,
|
||||
String param2,
|
||||
@PathVariable(name = "name", required = false) String param3,
|
||||
@PathVariable("name") Optional<String> param4) {
|
||||
@PathVariable("name") Optional<String> param4,
|
||||
@PathVariable Mono<String> param5) {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
|
|||
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.core.annotation.SynthesizingMethodParameter;
|
||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
|
|
@ -61,7 +62,8 @@ public class RequestAttributeMethodArgumentResolverTests {
|
|||
public void setup() throws Exception {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
context.refresh();
|
||||
this.resolver = new RequestAttributeMethodArgumentResolver(context.getBeanFactory());
|
||||
ReactiveAdapterRegistry adapterRegistry = new ReactiveAdapterRegistry();
|
||||
this.resolver = new RequestAttributeMethodArgumentResolver(context.getBeanFactory(), adapterRegistry);
|
||||
|
||||
ServerHttpRequest request = MockServerHttpRequest.get("/").build();
|
||||
this.exchange = new DefaultServerWebExchange(request, new MockServerHttpResponse());
|
||||
|
|
@ -74,6 +76,15 @@ public class RequestAttributeMethodArgumentResolverTests {
|
|||
public void supportsParameter() throws Exception {
|
||||
assertTrue(this.resolver.supportsParameter(new MethodParameter(this.handleMethod, 0)));
|
||||
assertFalse(this.resolver.supportsParameter(new MethodParameter(this.handleMethod, 4)));
|
||||
try {
|
||||
this.resolver.supportsParameter(new MethodParameter(this.handleMethod, 5));
|
||||
fail();
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
assertTrue("Unexpected error message:\n" + ex.getMessage(),
|
||||
ex.getMessage().startsWith(
|
||||
"RequestAttributeMethodArgumentResolver doesn't support reactive type wrapper"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -151,7 +162,8 @@ public class RequestAttributeMethodArgumentResolverTests {
|
|||
@RequestAttribute("specialFoo") Foo namedFoo,
|
||||
@RequestAttribute(name="foo", required = false) Foo notRequiredFoo,
|
||||
@RequestAttribute(name="foo") Optional<Foo> optionalFoo,
|
||||
String notSupported) {
|
||||
String notSupported,
|
||||
@RequestAttribute Mono<Foo> alsoNotSupported) {
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import rx.RxReactiveStreams;
|
|||
import rx.Single;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.core.codec.StringDecoder;
|
||||
import org.springframework.http.codec.DecoderHttpMessageReader;
|
||||
import org.springframework.http.codec.HttpMessageReader;
|
||||
|
|
@ -69,7 +70,7 @@ public class RequestBodyArgumentResolverTests {
|
|||
public void setup() {
|
||||
List<HttpMessageReader<?>> readers = new ArrayList<>();
|
||||
readers.add(new DecoderHttpMessageReader<>(new StringDecoder()));
|
||||
this.resolver = new RequestBodyArgumentResolver(readers);
|
||||
this.resolver = new RequestBodyArgumentResolver(readers, new ReactiveAdapterRegistry());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import org.junit.Test;
|
|||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.core.annotation.SynthesizingMethodParameter;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
|
|
@ -32,6 +33,7 @@ import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
|||
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.server.adapter.DefaultServerWebExchange;
|
||||
|
||||
|
|
@ -52,18 +54,21 @@ public class RequestHeaderMapMethodArgumentResolverTests {
|
|||
private MethodParameter paramMultiValueMap;
|
||||
private MethodParameter paramHttpHeaders;
|
||||
private MethodParameter paramUnsupported;
|
||||
private MethodParameter paramAlsoUnsupported;
|
||||
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
resolver = new RequestHeaderMapMethodArgumentResolver();
|
||||
resolver = new RequestHeaderMapMethodArgumentResolver(new ReactiveAdapterRegistry());
|
||||
request = MockServerHttpRequest.get("/").build();
|
||||
|
||||
Method method = getClass().getMethod("params", Map.class, MultiValueMap.class, HttpHeaders.class, Map.class);
|
||||
Method method = ReflectionUtils.findMethod(getClass(), "params", (Class<?>[]) null);
|
||||
paramMap = new SynthesizingMethodParameter(method, 0);
|
||||
paramMultiValueMap = new SynthesizingMethodParameter(method, 1);
|
||||
paramHttpHeaders = new SynthesizingMethodParameter(method, 2);
|
||||
paramUnsupported = new SynthesizingMethodParameter(method, 3);
|
||||
paramUnsupported = new SynthesizingMethodParameter(method, 3);
|
||||
paramAlsoUnsupported = new SynthesizingMethodParameter(method, 4);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -73,6 +78,15 @@ public class RequestHeaderMapMethodArgumentResolverTests {
|
|||
assertTrue("MultiValueMap parameter not supported", resolver.supportsParameter(paramMultiValueMap));
|
||||
assertTrue("HttpHeaders parameter not supported", resolver.supportsParameter(paramHttpHeaders));
|
||||
assertFalse("non-@RequestParam map supported", resolver.supportsParameter(paramUnsupported));
|
||||
try {
|
||||
this.resolver.supportsParameter(this.paramAlsoUnsupported);
|
||||
fail();
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
assertTrue("Unexpected error message:\n" + ex.getMessage(),
|
||||
ex.getMessage().startsWith(
|
||||
"RequestHeaderMapMethodArgumentResolver doesn't support reactive type wrapper"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -132,10 +146,12 @@ public class RequestHeaderMapMethodArgumentResolverTests {
|
|||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void params(@RequestHeader Map<?, ?> param1,
|
||||
@RequestHeader MultiValueMap<?, ?> param2,
|
||||
@RequestHeader HttpHeaders param3,
|
||||
Map<?,?> unsupported) {
|
||||
public void params(
|
||||
@RequestHeader Map<?, ?> param1,
|
||||
@RequestHeader MultiValueMap<?, ?> param2,
|
||||
@RequestHeader HttpHeaders param3,
|
||||
Map<?,?> unsupported,
|
||||
@RequestHeader Mono<Map<?, ?>> alsoUnsupported) {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import reactor.test.StepVerifier;
|
|||
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.core.annotation.SynthesizingMethodParameter;
|
||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
|
|
@ -64,13 +65,15 @@ public class RequestHeaderMethodArgumentResolverTests {
|
|||
private MethodParameter paramNamedValueMap;
|
||||
private MethodParameter paramDate;
|
||||
private MethodParameter paramInstant;
|
||||
private MethodParameter paramMono;
|
||||
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
context.refresh();
|
||||
this.resolver = new RequestHeaderMethodArgumentResolver(context.getBeanFactory());
|
||||
ReactiveAdapterRegistry adapterRegistry = new ReactiveAdapterRegistry();
|
||||
this.resolver = new RequestHeaderMethodArgumentResolver(context.getBeanFactory(), adapterRegistry);
|
||||
|
||||
this.request = MockServerHttpRequest.get("/").build();
|
||||
|
||||
|
|
@ -87,6 +90,7 @@ public class RequestHeaderMethodArgumentResolverTests {
|
|||
this.paramNamedValueMap = new SynthesizingMethodParameter(method, 5);
|
||||
this.paramDate = new SynthesizingMethodParameter(method, 6);
|
||||
this.paramInstant = new SynthesizingMethodParameter(method, 7);
|
||||
this.paramMono = new SynthesizingMethodParameter(method, 8);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -95,6 +99,15 @@ public class RequestHeaderMethodArgumentResolverTests {
|
|||
assertTrue("String parameter not supported", resolver.supportsParameter(paramNamedDefaultValueStringHeader));
|
||||
assertTrue("String array parameter not supported", resolver.supportsParameter(paramNamedValueStringArray));
|
||||
assertFalse("non-@RequestParam parameter supported", resolver.supportsParameter(paramNamedValueMap));
|
||||
try {
|
||||
this.resolver.supportsParameter(this.paramMono);
|
||||
fail();
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
assertTrue("Unexpected error message:\n" + ex.getMessage(),
|
||||
ex.getMessage().startsWith(
|
||||
"RequestHeaderMethodArgumentResolver doesn't support reactive type wrapper"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -237,7 +250,8 @@ public class RequestHeaderMethodArgumentResolverTests {
|
|||
@RequestHeader("${systemProperty}") String param5,
|
||||
@RequestHeader("name") Map<?, ?> unsupported,
|
||||
@RequestHeader("name") Date dateParam,
|
||||
@RequestHeader("name") Instant instantParam) {
|
||||
@RequestHeader("name") Instant instantParam,
|
||||
@RequestHeader Mono<String> alsoNotSupported) {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,8 +23,10 @@ import java.util.Map;
|
|||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
|
||||
|
|
@ -37,6 +39,7 @@ import org.springframework.web.server.adapter.DefaultServerWebExchange;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.springframework.web.method.MvcAnnotationPredicates.requestParam;
|
||||
|
||||
/**
|
||||
|
|
@ -52,7 +55,7 @@ public class RequestParamMapMethodArgumentResolverTests {
|
|||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
this.resolver = new RequestParamMapMethodArgumentResolver();
|
||||
this.resolver = new RequestParamMapMethodArgumentResolver(new ReactiveAdapterRegistry());
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -69,6 +72,17 @@ public class RequestParamMapMethodArgumentResolverTests {
|
|||
|
||||
param = this.testMethod.annotNotPresent(RequestParam.class).arg(Map.class);
|
||||
assertFalse(this.resolver.supportsParameter(param));
|
||||
|
||||
try {
|
||||
param = this.testMethod.annot(requestParam()).arg(Mono.class, Map.class);
|
||||
this.resolver.supportsParameter(param);
|
||||
fail();
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
assertTrue("Unexpected error message:\n" + ex.getMessage(),
|
||||
ex.getMessage().startsWith(
|
||||
"RequestParamMapMethodArgumentResolver doesn't support reactive type wrapper"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -120,7 +134,8 @@ public class RequestParamMapMethodArgumentResolverTests {
|
|||
@RequestParam Map<?, ?> param1,
|
||||
@RequestParam MultiValueMap<?, ?> param2,
|
||||
@RequestParam("name") Map<?, ?> param3,
|
||||
Map<?, ?> param4) {
|
||||
Map<?, ?> param4,
|
||||
@RequestParam Mono<Map<?, ?>> paramMono) {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
package org.springframework.web.reactive.result.method.annotation;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
import java.time.Duration;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
|
|
@ -26,12 +27,14 @@ import reactor.core.publisher.Mono;
|
|||
import reactor.test.StepVerifier;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
|
||||
import org.springframework.web.method.MvcAnnotationPredicates;
|
||||
import org.springframework.web.method.ResolvableMethod;
|
||||
import org.springframework.web.reactive.BindingContext;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
|
@ -43,6 +46,7 @@ import static org.junit.Assert.assertEquals;
|
|||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.springframework.core.ResolvableType.forClassWithGenerics;
|
||||
import static org.springframework.web.method.MvcAnnotationPredicates.requestParam;
|
||||
|
||||
|
|
@ -63,7 +67,8 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
@Before
|
||||
public void setup() throws Exception {
|
||||
|
||||
this.resolver = new RequestParamMethodArgumentResolver(null, true);
|
||||
ReactiveAdapterRegistry adapterRegistry = new ReactiveAdapterRegistry();
|
||||
this.resolver = new RequestParamMethodArgumentResolver(null, adapterRegistry, true);
|
||||
|
||||
ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();
|
||||
initializer.setConversionService(new DefaultFormattingConversionService());
|
||||
|
|
@ -73,7 +78,6 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
|
||||
@Test
|
||||
public void supportsParameter() {
|
||||
this.resolver = new RequestParamMethodArgumentResolver(null, true);
|
||||
|
||||
MethodParameter param = this.testMethod.annot(requestParam().notRequired("bar")).arg(String.class);
|
||||
assertTrue(this.resolver.supportsParameter(param));
|
||||
|
|
@ -96,11 +100,42 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
param = this.testMethod.annot(requestParam().notRequired()).arg(String.class);
|
||||
assertTrue(this.resolver.supportsParameter(param));
|
||||
|
||||
param = this.testMethod.annotNotPresent(RequestParam.class).arg(String.class);
|
||||
this.resolver = new RequestParamMethodArgumentResolver(null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesNotSupportParameterWithDefaultResolutionTurnedOff() {
|
||||
ReactiveAdapterRegistry adapterRegistry = new ReactiveAdapterRegistry();
|
||||
this.resolver = new RequestParamMethodArgumentResolver(null, adapterRegistry, false);
|
||||
|
||||
MethodParameter param = this.testMethod.annotNotPresent(RequestParam.class).arg(String.class);
|
||||
assertFalse(this.resolver.supportsParameter(param));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesNotSupportReactiveWrapper() {
|
||||
MethodParameter param;
|
||||
try {
|
||||
param = this.testMethod.annot(requestParam()).arg(Mono.class, String.class);
|
||||
this.resolver.supportsParameter(param);
|
||||
fail();
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
assertTrue("Unexpected error message:\n" + ex.getMessage(),
|
||||
ex.getMessage().startsWith(
|
||||
"RequestParamMethodArgumentResolver doesn't support reactive type wrapper"));
|
||||
}
|
||||
try {
|
||||
param = this.testMethod.annotNotPresent(RequestParam.class).arg(Mono.class, String.class);
|
||||
this.resolver.supportsParameter(param);
|
||||
fail();
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
assertTrue("Unexpected error message:\n" + ex.getMessage(),
|
||||
ex.getMessage().startsWith(
|
||||
"RequestParamMethodArgumentResolver doesn't support reactive type wrapper"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveWithQueryString() throws Exception {
|
||||
MethodParameter param = this.testMethod.annot(requestParam().notRequired("bar")).arg(String.class);
|
||||
|
|
@ -208,7 +243,7 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
}
|
||||
|
||||
private Object resolve(MethodParameter parameter, ServerWebExchange exchange) {
|
||||
return this.resolver.resolveArgument(parameter, this.bindContext, exchange).blockMillis(0);
|
||||
return this.resolver.resolveArgument(parameter, this.bindContext, exchange).block(Duration.ZERO);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -219,6 +254,7 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
@RequestParam("name") Map<?, ?> param3,
|
||||
@RequestParam Map<?, ?> param4,
|
||||
String stringNotAnnot,
|
||||
Mono<String> monoStringNotAnnot,
|
||||
@RequestParam("name") String paramRequired,
|
||||
@RequestParam(name = "name", required = false) String paramNotRequired,
|
||||
@RequestParam("name") Optional<Integer> paramOptional,
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import org.junit.Test;
|
|||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
|
|
@ -43,7 +44,8 @@ import static org.mockito.Mockito.*;
|
|||
*/
|
||||
public class ServerWebExchangeArgumentResolverTests {
|
||||
|
||||
private final ServerWebExchangeArgumentResolver resolver = new ServerWebExchangeArgumentResolver();
|
||||
private final ServerWebExchangeArgumentResolver resolver =
|
||||
new ServerWebExchangeArgumentResolver(new ReactiveAdapterRegistry());
|
||||
|
||||
private ServerWebExchange exchange;
|
||||
|
||||
|
|
@ -67,6 +69,15 @@ public class ServerWebExchangeArgumentResolverTests {
|
|||
assertTrue(this.resolver.supportsParameter(this.testMethod.arg(ServerHttpResponse.class)));
|
||||
assertTrue(this.resolver.supportsParameter(this.testMethod.arg(HttpMethod.class)));
|
||||
assertFalse(this.resolver.supportsParameter(this.testMethod.arg(String.class)));
|
||||
try {
|
||||
this.resolver.supportsParameter(this.testMethod.arg(Mono.class, ServerWebExchange.class));
|
||||
fail();
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
assertTrue("Unexpected error message:\n" + ex.getMessage(),
|
||||
ex.getMessage().startsWith(
|
||||
"ServerWebExchangeArgumentResolver doesn't support reactive type wrapper"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -91,7 +102,8 @@ public class ServerWebExchangeArgumentResolverTests {
|
|||
ServerHttpResponse response,
|
||||
WebSession session,
|
||||
HttpMethod httpMethod,
|
||||
String s) {
|
||||
String s,
|
||||
Mono<ServerWebExchange> monoExchange) {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
|
|||
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.core.annotation.SynthesizingMethodParameter;
|
||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
|
|
@ -44,8 +45,14 @@ import org.springframework.web.server.adapter.DefaultServerWebExchange;
|
|||
import org.springframework.web.server.session.MockWebSessionManager;
|
||||
import org.springframework.web.server.session.WebSessionManager;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link SessionAttributeMethodArgumentResolver}.
|
||||
|
|
@ -67,7 +74,8 @@ public class SessionAttributeMethodArgumentResolverTests {
|
|||
public void setup() throws Exception {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
context.refresh();
|
||||
this.resolver = new SessionAttributeMethodArgumentResolver(context.getBeanFactory());
|
||||
ReactiveAdapterRegistry adapterRegistry = new ReactiveAdapterRegistry();
|
||||
this.resolver = new SessionAttributeMethodArgumentResolver(context.getBeanFactory(), adapterRegistry);
|
||||
|
||||
this.session = mock(WebSession.class);
|
||||
WebSessionManager sessionManager = new MockWebSessionManager(this.session);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package org.springframework.web.reactive.result.method.annotation
|
|||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.springframework.core.MethodParameter
|
||||
import org.springframework.core.ReactiveAdapterRegistry
|
||||
import org.springframework.core.annotation.SynthesizingMethodParameter
|
||||
import org.springframework.format.support.DefaultFormattingConversionService
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest
|
||||
|
|
@ -34,7 +35,7 @@ class RequestParamMethodArgumentResolverKotlinTests {
|
|||
|
||||
@Before
|
||||
fun setup() {
|
||||
this.resolver = RequestParamMethodArgumentResolver(null, true)
|
||||
this.resolver = RequestParamMethodArgumentResolver(null, ReactiveAdapterRegistry(), true)
|
||||
this.request = MockServerHttpRequest.get("/").build()
|
||||
val initializer = ConfigurableWebBindingInitializer()
|
||||
initializer.conversionService = DefaultFormattingConversionService()
|
||||
|
|
|
|||
Loading…
Reference in New Issue