I am using Spring Boot 1.5.2.RELEASE and not able to incorporate JSR - 349 ( bean validation 1.1 ) for @RequestParam
& @PathVariable
at method itself.
For POST requests, if method parameter is a Java POJO then annotating that parameter with @Valid
is working fine but annotating @RequestParam
& @PathVariable
with something like @NotEmpty
, @Email
not working.
I have annotated controller class with Spring's @Validated
There are lots of questions on SO and I have commented on this answer that its not working for me.
Spring Boot includes - validation-api-1.1.0.Final.jar
and hibernate-validator-5.3.4.Final.jar
.
Am I missing anything?
Example 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;
}
Below handler is never called when I send empty values or not well formed email address for email
& control always goes to with in testValidated
method.
@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.
I had asked the question after more than two days of unsuccessful hit & trial. Lots of confusing answers are out there because of confusions around Spring Validations and JSR validations, how Spring invokes JSR validators, changes in JSR standards & types of validations supported.
Finally, this article helped a lot.
I solved problem in two steps,
1.Added following beans to my 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's @Validated annotation on my controller like below,
@RestController
@RequestMapping("/...")
@Validated
public class MyRestController {
}
Validated is - org.springframework.validation.annotation.Validated
This set up doesn't affected @Valid
annotations for @RequestBody
validations in same controller and those continued to work as those were.
So now, I can trigger validations like below for methods in MyRestController
class,
@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 in exception handler for exception - ConstraintViolationException
though since @Validated
throws this exception while @Valid
throws MethodArgumentNotValidException
Spring @Validated @Controller did not mapped when adding @Validated. Removal of any inheritance from controller itself did help. Otherwise Sabir Khan's answer worked and did help.
来源:https://stackoverflow.com/questions/44320678/jsr-349-bean-validation-for-spring-restcontroller-with-spring-boot