JSR - 349 bean validation for Spring @RestController with Spring Boot
I am using Spring Boot 1.5.2.RELEASE and cannot enable JSR-349 (bean validation 1.1) for @RequestParam
and @PathVariable
in the method itself.
For POST-search if the method parameter is a Java POJO, annotating this parameter using @Valid
works fine, but annotating @RequestParam
and @PathVariable
with something @NotEmpty
, @Email
does not work.
I have an annotated controller class with Spring @Validated
There are many questions on SO and I commented on this answer that it didn't work for me.
Spring Boot includes - validation-api-1.1.0.Final.jar
and hibernate-validator-5.3.4.Final.jar
.
Did I miss something?
Sample code,
@RequestMapping(method = RequestMethod.GET, value = "/testValidated" , consumes=MediaType.APPLICATION_JSON_VALUE, produces =MediaType.APPLICATION_JSON_VALUE )
public ResponseBean<String> testValidated(@Email @NotEmpty @RequestParam("email") String email){
ResponseBean<String> response = new ResponseBean<>();
response.setResponse(Constants.SUCCESS);
response.setMessage("testValidated");
logger.error("Validator Not called");
return response;
}
The below handler is never called when I send empty values ββor a malformed email for email
, and control is always done using the method testValidated
.
@ExceptionHandler(ConstraintViolationException.class)
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ResponseBean handle(ConstraintViolationException exception){
StringBuilder messages = new StringBuilder();
ResponseBean response = new ResponseBean();
exception.getConstraintViolations().forEach(entry -> messages.append(entry.getMessage()+"\n"));
response.setResponse(Constants.FAILURE);
response.setErrorcode(Constants.ERROR_CODE_BAD_REQUEST);
response.setMessage(messages.toString());
return response;
}
ResponseBean<T>
is my application specific class.
source to share
I asked the question after more than two days of a bad hit and trial. There are many confusing answers due to the confusion around Spring validation and JSR validation, how Spring invokes JSR validations, changes to JSR standards, and the types of assertions supported.
Finally, this article helped a lot.
I solved the problem in two steps,
1.Added the following beans to mine Configuration
- without these beans nothing works.
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
MethodValidationPostProcessor mvProcessor = new MethodValidationPostProcessor();
mvProcessor.setValidator(validator());
return mvProcessor;
}
@Bean
public LocalValidatorFactoryBean validator(){
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.setProviderClass(HibernateValidator.class);
validator.afterPropertiesSet();
return validator;}
2.Placed Spring @ Verified annotation on my controller like below,
@RestController
@RequestMapping("/...")
@Validated
public class MyRestController {
}
Confirmed - org.springframework.validation.annotation.Validated
This setting has no effect on the annotations @Valid
for @RequestBody
validation in the same controller, and they continued to work the way they were.
So now I can run checks as below for class methods MyRestController
,
@RequestMapping(method = RequestMethod.GET, value = "/testValidated" , consumes=MediaType.APPLICATION_JSON_VALUE, produces =MediaType.APPLICATION_JSON_VALUE )
public ResponseBean<String> testValidated(@Email(message="email RequestParam is not a valid email address") @NotEmpty(message="email RequestParam is empty") @RequestParam("email") String email){
ResponseBean<String> response = new ResponseBean<>();
....
return response;
}
I had to add another handler to the exception handler for the exception - ConstraintViolationException
but since it is @Validated
throwing this exception and @Valid
throwsMethodArgumentNotValidException
source to share