Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

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();
    }
}
share|improve this question
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.