This example is a bit contrived; I've simplified it to remove extraneous details and to focus on the problem I am having. I have a validator that looks like this:
@Component
public class UniqueUsernameValidator implements ConstraintValidator<UniqueUsername, String> {
@Autowired
UsernameService usernameService;
@Override
public void initialize(UniqueUsername uniqueUsername) {
}
@Override
public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
return !usernameService.exists(s);
}
}
I call the validator from my controller like this:
@RequestMapping
public void checkUsername(Model model, User user) {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<User>> constraintViolations = validator.validateProperty(user, "username");
model.addAttribute("error", constraintViolations.size() > 0);
}
However, I keep getting an NullPointerException exception. I added a breakpoint in my validator and saw that usernameService was null. Why isn't it getting autowired? Initially I thought it was because I hadn't annotated the validator with @Component, but I still have the same problem even after annotating it. The UsernameService class has already been annotated with @Service and I can verify that its constructor is getting called.
I am new to Spring, so I'm not even sure if it is alright to wire a service into a validator. What am I doing wrong?
In Spring, you need to obtain ValidatorFactory (or Validator itself) via LocalValidatorFactoryBean instead of Validation.buildDefaultValidatorFactory(), as described in the reference.
@Autowired
Validator validator;
@RequestMapping
public void checkUsername(Model model, User user) {
Set<ConstraintViolation<User>> constraintViolations = validator.validateProperty(user, "username");
model.addAttribute("error", constraintViolations.size() > 0);
}
-
<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
EDIT: But perhaps the better way to do it is to use Spring MVC's automatic validation with @Valid annotation:
@RequestMapping
public void checkUsername(Model model, @Valid User user, BindingResult result) {
if (result.hasErrors()) {
...
}
}
This also requires <mvc:annotation-driven/> in the config.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With