I have created a Spring MVC REST service using Bean Validation 1.2 with the following method:
@RequestMapping(value = "/valid")
public String validatedMethod(@Valid ValidObject object) {
}
If object isn't valid, Tomcat informs me that The request sent by the client was syntactically incorrect.
and my validatedMethod
is never called.
How can I get the message that was defined in the ValidObject
bean? Should I use some filter or interceptor?
I know that I can rewrite like below, to get the set of ConstraintViolation
s from the injected Validator
, but the above seems more neat...
@RequestMapping(value = "/valid")
public String validatedMethod(ValidObject object) {
Set<ConstraintViolation<ValidObject>> constraintViolations = validator
.validate(object);
if (constraintViolations.isEmpty()) {
return "valid";
} else {
final StringBuilder message = new StringBuilder();
constraintViolations.forEach((action) -> {
message.append(action.getPropertyPath());
message.append(": ");
message.append(action.getMessage());
});
return message.toString();
}
}
I believe a better way of doing this is using ExceptionHandler
.
In your Controller
you can write ExceptionHandler
to handle different exceptions. Below is the code for the same:
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public ValidationFailureResponse validationError(MethodArgumentNotValidException ex) {
BindingResult result = ex.getBindingResult();
final List<FieldError> fieldErrors = result.getFieldErrors();
return new ValidationFailureResponse((FieldError[])(fieldErrors.toArray(new FieldError[fieldErrors.size()])));
}
When you send a bad request to the Controller, the validator throws an exception of type MethodArgumentNotValidException
. So the ideal way would be to write an exception handler to specifically handle this exception.
There you can create a beautiful response to tell the user of things which went wrong.
I advocate this, because you have to write this just once and many Controller
methods can use it. :)
UPDATE
When you use the @Valid annotation for a method argument in the Controller
, the validator is invoked automatically and it tries to validate the object, if the object is invalid, it throws MethodArgumentNotValidException
.
If Spring finds an ExceptionHandler
method for this exception it will execute the code inside this method.
You just need to make sure that the method above is present in your Controller.
Now there is another case when you have multiple Controller
s where you want to validate the method arguments. In this case I suggest you to create a ExceptionResolver
class and put this method there. Make your Controller
s extend this class and your job is done.