I've noticed that JSR-303 validation is completely ignored in Spring when a custom Validator bean annotated with @Component is declared. Interestingly enough said custom validator doesn't even have to filled in or used by any of the classes. The fact that its component scanned by Spring appears to be enough to make Spring skip JSR-303 validation during object binding altogether. Removing @Component from custom Validator and restarting web application enables JSR-303 validation as expected. Annotating custom validators with @Component has its uses eg to have Spring Autowire dependencies.
Consider simple example below:
/* Simple JSR-303 annotated User object */
public class User {
@NotNull @Size(min = 2, max = 5)
protected String username;
@Size(min = 2, max = 32)
protected String firstName;
@Size(min = 2, max = 32)
protected String lastName;
@NotNull @Past @DateTimeFormat(pattern="dd/MM/yyyy")
protected Date dateOfBirth;
@NotNull @Email
protected String email;
protected String phone;
//getters and setters
}
/* Controller example */
@RestController
public class UserController {
@PostMapping("/users/register")
public ResponseEntity postUser(@Valid @RequestBody User user, BindingResult result) {
if (result.hasErrors()) {
return new ResponseEntity(result.getAllErrors(), HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity(user, HttpStatus.CREATED);
}
}
/* Custom validator (doesn't even have to be in use) */
@Component //commenting out @Component annotation enables JSR-303 again
public class SomeValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
//just an example
return false;
}
@Override
public void validate(Object target, Errors errors) {
//empty
}
}
I was scratching my head over this one and couldn't figure out why my JSR-303 objects weren't validated but I managed to narrow it down and replicate this with a Spring Boot project containing above classes. Why is that? Am I missing something here or is this a Spring bug?
applicationContext.getBeansOfTypeto verify that the@Componentannotation results in a Spring bean being created.SomeValidatoris part of the Spring Validation API, maybe you have to configure that Spring uses both validation APIs together? see stackoverflow.com/a/26733582/649686 for an example