-
Notifications
You must be signed in to change notification settings - Fork 38.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bean Validation invocation API for use with individual values and constraints [SPR-11900] #16519
Comments
Juergen Hoeller commented As per our discussion today, we're going to revisit this from a slightly different perspective: Calling a Bean Validation provider for individual values to validate, given a set of constraint annotations... Those may come from a specific method parameter but also from a field or the like. Reusing the method validation feature in Bean Validation 1.1 is not going to get us there since it doesn't allow for the individual validation of parameters, just for validating all parameters at once. This proves to be problematic with our existing support for Juergen |
Juergen Hoeller commented Looking at the inner APIs of Hibernate Validator 5, there doesn't seem to be an easy way to validate a single value within the context of a specific method parameter at all. Ideally, we'd either get such an API or even a super-plain API that just takes a value to validate plus an array of annotations, independent from the source of those annotations... Ironically, Hibernate Validator 4.3 did provide a proprietary validateParameter method for an individual parameter. However, that API is deprecated there, so nothing to base a new Spring feature on if there's no equivalent in Hibernate Validator 5. If we get some such API in Hibernate Validator 5, we could support the Hibernate Validator 4.3 variant as a fallback. Juergen |
Baron Roberts commented I was able to achieve controller parameter validation using the First I created a custom annotation that will be placed on the controller methods I wish to be validated. I could have accomplished the validation without the use of the annotation and applied the advice to all controller methods but I wanted the ability to be more selective. Here is the code for the annotation: package com.cthing.validation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Marks a controller method whose parameters are to be validated using
* Java and Hibernate validators.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ValidateParams {
} The heart of the solution is the validation aspect. I apply the advice to any controller method that has the above annotation. Using a JSR 303 package com.cthing.controller;
import java.lang.reflect.Method;
import java.util.Set;
import javax.inject.Inject;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidatorFactory;
import javax.validation.executable.ExecutableValidator;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
/**
* Performs validation on controller parameters annotated with {@link com.cthing.validation.ValidateParams}.
*/
@Aspect
@Component
public class ValidateParamsAdvice {
private final ValidatorFactory validatorFactory;
@Inject
public ValidateParamsAdvice(final ValidatorFactory jsr303ValidationFactory) {
this.validatorFactory = jsr303ValidationFactory;
}
/**
* Validates controller method parameters.
*
* @param joinPoint Matched method join point
*/
@Before("execution(public * com.cthing.controller.*.*(..)) && @annotation(com.cthing.validation.ValidateParams)")
public void validateMethodParams(final JoinPoint joinPoint) {
final Object controller = joinPoint.getThis();
final Method controllerMethod = ((MethodSignature)joinPoint.getSignature()).getMethod();
final Object[] params = joinPoint.getArgs();
final ExecutableValidator executableValidator = this.validatorFactory.getValidator().forExecutables();
final Set<ConstraintViolation<Object>> violations =
executableValidator.validateParameters(controller, controllerMethod, params);
if (!violations.isEmpty()) {
throw new ConstraintViolationException(violations);
}
}
} |
Sam Brannen commented Thanks for sharing, Baron! The API provided via |
Baron Roberts commented Any update on this issue? |
Juergen Hoeller commented The problem with the Bean Validation 1.1 I suppose we need to get in touch with the HV team and ask for introducing such a |
Filip Panovski commented Hi, has there been any update on this issue? Is it still pending Hibernate updates, or has it been postponed indefinitely? Definitely a very nice feature that would make |
Superseded by #30645. |
Rossen Stoyanchev opened SPR-11900 and commented
The logic in MethodValidationInterceptor is pretty useful. However it is currently not easy to use if not in the context of AOP method interception. I'd like to be able to use it for invoking an
@MVC
HandlerMethod with the ability to validate method arguments first and then the method return value as a separate step.Affects: 4.0.5
Issue Links:
@Validated
support on Iterables (and implementors)10 votes, 12 watchers
The text was updated successfully, but these errors were encountered: