Add method validation to Spring MVC
See gh-29825
This commit is contained in:
committed by
rstoyanchev
parent
cb04c3b335
commit
bd054a4918
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2023 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.
|
||||
@@ -16,7 +16,11 @@
|
||||
|
||||
package org.springframework.web.bind.support;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.validation.DataBinder;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
|
||||
@@ -32,6 +36,8 @@ public class DefaultDataBinderFactory implements WebDataBinderFactory {
|
||||
@Nullable
|
||||
private final WebBindingInitializer initializer;
|
||||
|
||||
private boolean methodValidationApplicable;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code DefaultDataBinderFactory} instance.
|
||||
@@ -43,6 +49,17 @@ public class DefaultDataBinderFactory implements WebDataBinderFactory {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configure flag to signal whether validation will be applied to handler
|
||||
* method arguments, which is the case if Bean Validation is enabled in
|
||||
* Spring MVC, and method parameters have {@code @Constraint} annotations.
|
||||
* @since 6.1
|
||||
*/
|
||||
public void setMethodValidationApplicable(boolean methodValidationApplicable) {
|
||||
this.methodValidationApplicable = methodValidationApplicable;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@link WebDataBinder} for the given target object and
|
||||
* initialize it through a {@link WebBindingInitializer}.
|
||||
@@ -87,4 +104,36 @@ public class DefaultDataBinderFactory implements WebDataBinderFactory {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}.
|
||||
* <p>By default, if the parameter has {@code @Valid}, Bean Validation is
|
||||
* excluded, deferring to method validation.
|
||||
*/
|
||||
@Override
|
||||
public WebDataBinder createBinder(
|
||||
NativeWebRequest webRequest, @Nullable Object target, String objectName,
|
||||
MethodParameter parameter) throws Exception {
|
||||
|
||||
WebDataBinder dataBinder = createBinder(webRequest, target, objectName);
|
||||
if (this.methodValidationApplicable) {
|
||||
MethodValidationInitializer.updateBinder(dataBinder, parameter);
|
||||
}
|
||||
return dataBinder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Excludes Bean Validation if the method parameter has {@code @Valid}.
|
||||
*/
|
||||
private static class MethodValidationInitializer {
|
||||
|
||||
public static void updateBinder(DataBinder binder, MethodParameter parameter) {
|
||||
for (Annotation annotation : parameter.getParameterAnnotations()) {
|
||||
if (annotation.annotationType().getName().equals("jakarta.validation.Valid")) {
|
||||
binder.setExcludedValidators(validator -> validator instanceof jakarta.validation.Validator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2023 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.
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.web.bind.support;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
@@ -24,6 +25,7 @@ import org.springframework.web.context.request.NativeWebRequest;
|
||||
* A factory for creating a {@link WebDataBinder} instance for a named target object.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.1
|
||||
*/
|
||||
public interface WebDataBinderFactory {
|
||||
@@ -40,4 +42,18 @@ public interface WebDataBinderFactory {
|
||||
WebDataBinder createBinder(NativeWebRequest webRequest, @Nullable Object target, String objectName)
|
||||
throws Exception;
|
||||
|
||||
/**
|
||||
* Variant of {@link #createBinder(NativeWebRequest, Object, String)} with a
|
||||
* {@link MethodParameter} for which the {@code DataBinder} is created. This
|
||||
* may provide more insight to initialize the {@link WebDataBinder}.
|
||||
* @since 6.1
|
||||
*/
|
||||
default WebDataBinder createBinder(
|
||||
NativeWebRequest webRequest, @Nullable Object target, String objectName,
|
||||
MethodParameter parameter) throws Exception {
|
||||
|
||||
return createBinder(webRequest, target, objectName);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 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.
|
||||
@@ -22,6 +22,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
@@ -35,6 +36,10 @@ import org.springframework.core.BridgeMethodResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.MergedAnnotation;
|
||||
import org.springframework.core.annotation.MergedAnnotationPredicates;
|
||||
import org.springframework.core.annotation.MergedAnnotations;
|
||||
import org.springframework.core.annotation.SynthesizingMethodParameter;
|
||||
import org.springframework.http.HttpStatusCode;
|
||||
import org.springframework.lang.NonNull;
|
||||
@@ -44,6 +49,7 @@ import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
/**
|
||||
@@ -84,6 +90,10 @@ public class HandlerMethod {
|
||||
|
||||
private final MethodParameter[] parameters;
|
||||
|
||||
private final boolean validateArguments;
|
||||
|
||||
private final boolean validateReturnValue;
|
||||
|
||||
@Nullable
|
||||
private HttpStatusCode responseStatus;
|
||||
|
||||
@@ -122,6 +132,8 @@ public class HandlerMethod {
|
||||
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
|
||||
ReflectionUtils.makeAccessible(this.bridgedMethod);
|
||||
this.parameters = initMethodParameters();
|
||||
this.validateArguments = MethodValidationInitializer.checkArguments(this.beanType, this.parameters);
|
||||
this.validateReturnValue = MethodValidationInitializer.checkReturnValue(this.beanType, this.bridgedMethod);
|
||||
evaluateResponseStatus();
|
||||
this.description = initDescription(this.beanType, this.method);
|
||||
}
|
||||
@@ -141,6 +153,8 @@ public class HandlerMethod {
|
||||
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(this.method);
|
||||
ReflectionUtils.makeAccessible(this.bridgedMethod);
|
||||
this.parameters = initMethodParameters();
|
||||
this.validateArguments = MethodValidationInitializer.checkArguments(this.beanType, this.parameters);
|
||||
this.validateReturnValue = MethodValidationInitializer.checkReturnValue(this.beanType, this.bridgedMethod);
|
||||
evaluateResponseStatus();
|
||||
this.description = initDescription(this.beanType, this.method);
|
||||
}
|
||||
@@ -177,6 +191,8 @@ public class HandlerMethod {
|
||||
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
|
||||
ReflectionUtils.makeAccessible(this.bridgedMethod);
|
||||
this.parameters = initMethodParameters();
|
||||
this.validateArguments = MethodValidationInitializer.checkArguments(this.beanType, this.parameters);
|
||||
this.validateReturnValue = MethodValidationInitializer.checkReturnValue(this.beanType, this.bridgedMethod);
|
||||
evaluateResponseStatus();
|
||||
this.description = initDescription(this.beanType, this.method);
|
||||
}
|
||||
@@ -193,6 +209,8 @@ public class HandlerMethod {
|
||||
this.method = handlerMethod.method;
|
||||
this.bridgedMethod = handlerMethod.bridgedMethod;
|
||||
this.parameters = handlerMethod.parameters;
|
||||
this.validateArguments = handlerMethod.validateArguments;
|
||||
this.validateReturnValue = handlerMethod.validateReturnValue;
|
||||
this.responseStatus = handlerMethod.responseStatus;
|
||||
this.responseStatusReason = handlerMethod.responseStatusReason;
|
||||
this.description = handlerMethod.description;
|
||||
@@ -212,6 +230,8 @@ public class HandlerMethod {
|
||||
this.method = handlerMethod.method;
|
||||
this.bridgedMethod = handlerMethod.bridgedMethod;
|
||||
this.parameters = handlerMethod.parameters;
|
||||
this.validateArguments = handlerMethod.validateArguments;
|
||||
this.validateReturnValue = handlerMethod.validateReturnValue;
|
||||
this.responseStatus = handlerMethod.responseStatus;
|
||||
this.responseStatusReason = handlerMethod.responseStatusReason;
|
||||
this.resolvedFromHandlerMethod = handlerMethod;
|
||||
@@ -290,6 +310,33 @@ public class HandlerMethod {
|
||||
return this.parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the method arguments are a candidate for method validation, which
|
||||
* is the case when there are parameter {@code jakarta.validation.Constraint}
|
||||
* annotations.
|
||||
* <p>The presence of {@code jakarta.validation.Valid} by itself does not
|
||||
* trigger method validation since such parameters are already validated at
|
||||
* the level of argument resolvers.
|
||||
* <p><strong>Note:</strong> if the class is annotated with {@link Validated},
|
||||
* this method returns false, deferring to method validation via AOP proxy.
|
||||
* @since 6.1
|
||||
*/
|
||||
public boolean shouldValidateArguments() {
|
||||
return this.validateArguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the method return value is a candidate for method validation, which
|
||||
* is the case when there are method {@code jakarta.validation.Constraint}
|
||||
* or {@code jakarta.validation.Valid} annotations.
|
||||
* <p><strong>Note:</strong> if the class is annotated with {@link Validated},
|
||||
* this method returns false, deferring to method validation via AOP proxy.
|
||||
* @since 6.1
|
||||
*/
|
||||
public boolean shouldValidateReturnValue() {
|
||||
return this.validateReturnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the specified response status, if any.
|
||||
* @since 4.3.8
|
||||
@@ -603,4 +650,38 @@ public class HandlerMethod {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks for the presence of {@code @Constraint} and {@code @Valid}
|
||||
* annotations on the method and method parameters.
|
||||
*/
|
||||
private static class MethodValidationInitializer {
|
||||
|
||||
private static final Predicate<MergedAnnotation<? extends Annotation>> INPUT_PREDICATE =
|
||||
MergedAnnotationPredicates.typeIn("jakarta.validation.Constraint");
|
||||
|
||||
private static final Predicate<MergedAnnotation<? extends Annotation>> OUTPUT_PREDICATE =
|
||||
MergedAnnotationPredicates.typeIn("jakarta.validation.Valid", "jakarta.validation.Constraint");
|
||||
|
||||
public static boolean checkArguments(Class<?> beanType, MethodParameter[] parameters) {
|
||||
if (AnnotationUtils.findAnnotation(beanType, Validated.class) == null) {
|
||||
for (MethodParameter parameter : parameters) {
|
||||
MergedAnnotations merged = MergedAnnotations.from(parameter.getParameterAnnotations());
|
||||
if (merged.stream().anyMatch(INPUT_PREDICATE)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean checkReturnValue(Class<?> beanType, Method method) {
|
||||
if (AnnotationUtils.findAnnotation(beanType, Validated.class) == null) {
|
||||
MergedAnnotations merged = MergedAnnotations.from(method, MergedAnnotations.SearchStrategy.TYPE_HIERARCHY);
|
||||
return merged.stream().anyMatch(OUTPUT_PREDICATE);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResol
|
||||
if (bindingResult == null) {
|
||||
// Bean property binding and validation;
|
||||
// skipped in case of binding failure on construction.
|
||||
WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name);
|
||||
WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name, parameter);
|
||||
if (binder.getTarget() != null) {
|
||||
if (!mavContainer.isBindingDisabled(name)) {
|
||||
bindRequestParameters(binder, webRequest);
|
||||
@@ -251,7 +251,7 @@ public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResol
|
||||
String[] paramNames = BeanUtils.getParameterNames(ctor);
|
||||
Class<?>[] paramTypes = ctor.getParameterTypes();
|
||||
Object[] args = new Object[paramTypes.length];
|
||||
WebDataBinder binder = binderFactory.createBinder(webRequest, null, attributeName);
|
||||
WebDataBinder binder = binderFactory.createBinder(webRequest, null, attributeName, parameter);
|
||||
String fieldDefaultPrefix = binder.getFieldDefaultPrefix();
|
||||
String fieldMarkerPrefix = binder.getFieldMarkerPrefix();
|
||||
boolean bindingFailure = false;
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright 2002-2023 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
|
||||
*
|
||||
* https://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.method.support;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import jakarta.validation.Validator;
|
||||
|
||||
import org.springframework.core.Conventions;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.MessageCodesResolver;
|
||||
import org.springframework.validation.beanvalidation.DefaultMethodValidator;
|
||||
import org.springframework.validation.beanvalidation.MethodValidationAdapter;
|
||||
import org.springframework.validation.beanvalidation.MethodValidationResult;
|
||||
import org.springframework.validation.beanvalidation.MethodValidator;
|
||||
import org.springframework.validation.beanvalidation.ParameterErrors;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
|
||||
import org.springframework.web.bind.support.WebBindingInitializer;
|
||||
import org.springframework.web.method.annotation.ModelFactory;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.validation.beanvalidation.MethodValidator} for
|
||||
* use with {@code @RequestMapping} methods. Helps to determine object names
|
||||
* and populates {@link BindingResult} method arguments with errors from
|
||||
* {@link MethodValidationResult#getBeanResults() beanResults}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 6.1
|
||||
*/
|
||||
public class HandlerMethodValidator extends DefaultMethodValidator {
|
||||
|
||||
|
||||
public HandlerMethodValidator(MethodValidationAdapter adapter) {
|
||||
super(adapter);
|
||||
adapter.setBindingResultNameResolver(this::determineObjectName);
|
||||
}
|
||||
|
||||
private String determineObjectName(MethodParameter param, @Nullable Object argument) {
|
||||
if (param.hasParameterAnnotation(RequestBody.class) || param.hasParameterAnnotation(RequestPart.class)) {
|
||||
return Conventions.getVariableNameForParameter(param);
|
||||
}
|
||||
else {
|
||||
return ((param.getParameterIndex() != -1) ?
|
||||
ModelFactory.getNameForParameter(param) :
|
||||
ModelFactory.getNameForReturnValue(argument, param));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void handleArgumentsResult(
|
||||
Object bean, Method method, Object[] arguments, Class<?>[] groups, MethodValidationResult result) {
|
||||
|
||||
if (result.getConstraintViolations().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (!result.getBeanResults().isEmpty()) {
|
||||
int bindingResultCount = 0;
|
||||
for (ParameterErrors errors : result.getBeanResults()) {
|
||||
for (Object arg : arguments) {
|
||||
if (arg instanceof BindingResult bindingResult) {
|
||||
if (bindingResult.getObjectName().equals(errors.getObjectName())) {
|
||||
bindingResult.addAllErrors(errors);
|
||||
bindingResultCount++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result.getAllValidationResults().size() == bindingResultCount) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
result.throwIfViolationsPresent();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a {@link MethodValidator} if Bean Validation is enabled in Spring MVC or WebFlux.
|
||||
* @param bindingInitializer for the configured Validator and MessageCodesResolver
|
||||
* @param parameterNameDiscoverer the {@code ParameterNameDiscoverer} to use
|
||||
* for {@link MethodValidationAdapter#setParameterNameDiscoverer}
|
||||
*/
|
||||
@Nullable
|
||||
public static MethodValidator from(
|
||||
@Nullable WebBindingInitializer bindingInitializer,
|
||||
@Nullable ParameterNameDiscoverer parameterNameDiscoverer) {
|
||||
|
||||
if (bindingInitializer instanceof ConfigurableWebBindingInitializer configurableInitializer) {
|
||||
if (configurableInitializer.getValidator() instanceof Validator validator) {
|
||||
MethodValidationAdapter validationAdapter = new MethodValidationAdapter(validator);
|
||||
if (parameterNameDiscoverer != null) {
|
||||
validationAdapter.setParameterNameDiscoverer(parameterNameDiscoverer);
|
||||
}
|
||||
MessageCodesResolver codesResolver = configurableInitializer.getMessageCodesResolver();
|
||||
if (codesResolver != null) {
|
||||
validationAdapter.setMessageCodesResolver(codesResolver);
|
||||
}
|
||||
return new HandlerMethodValidator(validationAdapter);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 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.
|
||||
@@ -30,6 +30,7 @@ import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.validation.beanvalidation.MethodValidator;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.bind.support.SessionStatus;
|
||||
import org.springframework.web.bind.support.WebDataBinderFactory;
|
||||
@@ -50,6 +51,8 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
||||
|
||||
private static final Object[] EMPTY_ARGS = new Object[0];
|
||||
|
||||
private static final Class<?>[] EMPTY_GROUPS = new Class<?>[0];
|
||||
|
||||
|
||||
private HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
|
||||
|
||||
@@ -58,6 +61,9 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
||||
@Nullable
|
||||
private WebDataBinderFactory dataBinderFactory;
|
||||
|
||||
@Nullable
|
||||
private MethodValidator methodValidator;
|
||||
|
||||
|
||||
/**
|
||||
* Create an instance from a {@code HandlerMethod}.
|
||||
@@ -121,6 +127,16 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
||||
this.dataBinderFactory = dataBinderFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link MethodValidator} to perform method validation with if the
|
||||
* controller method {@link #shouldValidateArguments()} or
|
||||
* {@link #shouldValidateReturnValue()}.
|
||||
* @since 6.1
|
||||
*/
|
||||
public void setMethodValidator(@Nullable MethodValidator methodValidator) {
|
||||
this.methodValidator = methodValidator;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Invoke the method after resolving its argument values in the context of the given request.
|
||||
@@ -149,7 +165,19 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Arguments: " + Arrays.toString(args));
|
||||
}
|
||||
return doInvoke(args);
|
||||
|
||||
Class<?>[] groups = getValidationGroups();
|
||||
if (shouldValidateArguments() && this.methodValidator != null) {
|
||||
this.methodValidator.validateArguments(getBean(), getBridgedMethod(), args, groups);
|
||||
}
|
||||
|
||||
Object returnValue = doInvoke(args);
|
||||
|
||||
if (shouldValidateReturnValue() && this.methodValidator != null) {
|
||||
this.methodValidator.validateReturnValue(getBean(), getBridgedMethod(), returnValue, groups);
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -194,6 +222,11 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
||||
return args;
|
||||
}
|
||||
|
||||
private Class<?>[] getValidationGroups() {
|
||||
return ((shouldValidateArguments() || shouldValidateReturnValue()) && this.methodValidator != null ?
|
||||
this.methodValidator.determineValidationGroups(getBean(), getBridgedMethod()) : EMPTY_GROUPS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the handler method with the given argument values.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user