I have a problem with Spring MVC which is as follows: I use JSR 303 validation in order to make sure properties of a bean (see PasswordInfo below) are neither empty nor null.
I am also checking a business logic rule i.e. that two passwords are identical.
The issue is that if one of the string fields (currentPassword and newPassword) is empty, it is still passed to the service layer by the controller in order to check the business logic rule and of course an IllegalArgumentException is raised!
Here is the PasswordInfo
bean:
@RooEquals
@RooJavaBean
public class PasswordInfo {
@NotNull(groups = { ValidationGroups.PasswordModification.class })
@NotEmpty(groups = { ValidationGroups.PasswordModification.class })
private String currentPassword;
@NotNull(groups = { ValidationGroups.PasswordModification.class, ValidationGroups.PasswordReset.class })
@NotEmpty(groups = { ValidationGroups.PasswordModification.class, ValidationGroups.PasswordReset.class })
@Size(min = 6, groups = { ValidationGroups.PasswordModification.class, ValidationGroups.PasswordReset.class })
private String newPassword;
...
Here is the relevant controller method:
@RequestMapping(value = "/preference/password", method = RequestMethod.POST, produces = "text/html")
public String modifyPassword(@ModelAttribute @Validated({ ValidationGroups.PasswordModification.class }) PasswordInfo passwordInfo,
BindingResult bindingResult, Model model, @CurrentMember Member member) {
if (!preferenceService.passwordsMatch(member.getPassword(), passwordInfo.getCurrentPassword())) {
bindingResult.rejectValue("currentPassword", "controller.preference.wrong_current_password");
}
if (bindingResult.hasErrors()) {
model.addAttribute("passwordInfo", passwordInfo);
return "preference/password";
}
preferenceService.modifyPassword(member, passwordInfo.getNewPassword());
return "redirect:/preference/password";
}
Here is the relevant service-layer method:
@Override
public boolean passwordsMatch(String encrypted, String plain) {
if (encrypted == null || encrypted.isEmpty() || plain == null || plain.isEmpty()) {
throw new IllegalArgumentException("One argument is null or empty");
}
return passwordEncoder.matches(plain, encrypted);
}
My concern is to avoid placing another bindingResults.hasErrors block such as:
if (bindingResult.hasErrors()) {
model.addAttribute("passwordInfo", passwordInfo);
return "preference/password";
}
...before the business logic check in order to avoid repeating myself...
Can anyone please suggest a clean solution to this problem?