4

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? What alternatives are there?

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();
    }
}

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.