i have problem with Thymeleaf when validating form. I'm trying to create simple user register form to learn Spring and i'm unfortunately stuck.
Here is my UserForm class
public class UserForm {
@NotEmpty
private String username;
@NotEmpty
private String password;
@NotEmpty
private String passwordConfirm;
\\ Getters and Setters
}
First problem is when I add my custom validator class in initBinder
@Autowired
private UserFormValidator formValidator;
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.setValidator(formValidator);
}
"Default" annotated by @NotEmpty validation stops working. This is exptected behavior?
Second problem is how can I show global reject messages in thymeleaf?
My validator class is like below
public class UserFormValidator implements Validator {
@Autowired
UserService userService;
@Override
public boolean supports(Class<?> clazz) {
return UserForm.class.isAssignableFrom(clazz);
}
@Override
public void validate(Object target, Errors errors) {
UserForm userForm = (UserForm) target;
if(!userForm.getPassword().equals(userForm.getPasswordConfirm())) {
errors.reject("passwords.no.match", "Passwords not match");
}
if(userService.findOneByUsername(userForm.getUsername()).isPresent()) {
errors.reject("user.exist", "User already exists (default)");
}
}
}
and post mapping from controller
@PostMapping("/create")
public String registerUser(@ModelAttribute("form") @Valid final UserForm form, BindingResult bindingResult) {
if(bindingResult.hasErrors()) {
return "newuser";
}
userService.saveUser(form);
return "redirect:/";
}
As "default" validation errors i can show by using exth:if="${#fields.hasErrors('passwordConfirm')}" i have no idea how can i show message for error passwords.no.match or check if this error occured?
By default spring boot uses bean validation to validated form object annotated with @Valid. If you want to use your custom validator and register it through @InitBinder, then bean validation will not take place, this is expected behavior. If you want to bean validation also works with your custom validation you need to do it manually inside your validator class or even in controller.
Here comes your second problem to show password not match error message. Inside your custom validator UserFormValidator.class while rejecting any value you need to use rejectValue() method like below:
@Override
public void validate(Object target, Errors errors) {
UserForm userForm = (UserForm) target;
if(!userForm.getPassword().equals(userForm.getPasswordConfirm())) {
errors.rejectValue("passwordConfirm", "passwords.no.match", "Passwords not match");
}
if(userService.findOneByUsername(userForm.getUsername()).isPresent()) {
errors.rejectValue("username", "user.exist", "User already exists (default)");
}
}
The rejectValue() method is used to add a validation error to the Errors object. The first parameter identifies which field the error is associated with. The second parameter is an error code which acts a message key for the messages.properties file (or messages_en.properties or messages_fr.properties etc, if these are being used). The third parameter of rejectValue() represents the fallback default message, which is displayed if no matching error code is found in the resource bundle.
Now you can show error messages using th:if="${#fields.hasErrors('passwordConfirm')}
inside your form.
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