I have a controller method like listed below whose argument is annotated with @Valid
to validate PasswordChange
object using a Hibernate validator @Constraint
. Both PasswordChange
and a sample constraint are listed below. As you can see, I am injecting up loginDao
inside the constraint. Is this an anti-pattern ?
The other alternative I can think of is injecting the daos into the PasswordChange
object so that the loginDao’s are available inside the implementations of ConstraintValidator<A, V>
. Somebody said that mixing data with business logic is an anti-pattern in spring.
Any suggestions are welcome.
Controller Method
@RequestMapping(value = "/passwordChange", method = RequestMethod.POST)
public @ResponseBody PasswordInfo passwordInfo(@RequestBody @Valid PasswordChange passwordChange)
throws PasswordChangeException {
return passwordService.changePassword(passwordChange.getLoginKey(), passwordChange.getOldPassword(), passwordChange.getNewPassword());
}
PasswordChange Bean
public class PasswordChange {
@LoginAttemptsExceeded
private String loginKey;
private String oldPassword;
private String newPassword;
@Autowired
private LoginDao loginDao;
private LoginEntity login;
private Person person;
public PasswordChange() {
}
public PasswordChange(String loginKey, String oldPassword, String newPassword) {
this.loginKey = loginKey;
this.oldPassword = oldPassword;
this.newPassword = newPassword;
}
@PostConstruct
public void postInit() {
login = loginDao.findByLogin(loginKey);
person = login.getCorePerson();
}
}
Sample Constraint
@Target({ FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = LoginAttemptsExceededValidatorLoginId.class)
@Documented
public @interface LoginAttemptsExceeded {
String message() default "{com.mrll.global.core.constraint.loginAttemptsExceeded}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Sample Constraint Validator
public final class LoginAttemptsExceededValidatorLoginId implements ConstraintValidator<LoginAttemptsExceeded, String> {
@Resource
private LoginDao loginDao;
private LoginAttemptsExceeded loginAttemptsExceeded;
@Override
public void initialize(final LoginAttemptsExceeded loginAttemptsExceeded) {
this.loginAttemptsExceeded = loginAttemptsExceeded;
}
/**
* Validation fails if the login attempts have exceeded the preset number.
* @param loginId
* @param constraintValidatorContext
* @return
*/
@Override
public boolean isValid(final String loginId, final ConstraintValidatorContext constraintValidatorContext) {
if(StringUtility.IsEmpty(loginId)) return false;
return !loginDao.findByLogin(loginId).isLoginAttemptsExceeded();
}
}