Hi
I want to have my password component validated:
Code:
public class PasswordView {
    private String password;
    private String passwordRepeat;
}
My requirements are:
if password is blank ( passwordRepeat does not matter) - return single error that password is blank
if password is less than 6 characters( passwordRepeat does not matter) - return single errror that password length is less than 6
if (password.length >=6 and !password.equals(passwordRepeat)) - return two errors that password and passwordRepeat do not match.
My initial implementation is:
create @PasswordFieldConstraint like:
Code:
@Documented
@Constraint(validatedBy = {})
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
@ReportAsSingleViolation
@NotBlank
@Size(min = 6, max = 25)
public @interface PasswordContraint {
    String message() default "{InvalidPassword.message}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}
and apply it on field:
Code:
public class PasswordView {
    @PasswordContraint
    private String password;
    private String passwordRepeat;
}
then create  class level constraint:
Code:
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE, ElementType.ANNOTATION_TYPE, ElementType.PARAMETER})
@Constraint( validatedBy = { PasswordViewValidator.class } )
public @interface PasswordViewConstraint {
    String message() default "{PasswordNotMatch.message}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}
PasswordViewValidator:
Code:
PasswordViewValidator{
 private String messageTemplate;
    @Override
    public void initialize(PasswordViewConstraint constraintAnnotation) {
        messageTemplate = constraintAnnotation.message();        
    }
    @Override
    public boolean isValid(PasswordView value,
            ConstraintValidatorContext context) {
        boolean result = isValid(value);
        if(!result){
            setConstraintViolations(context);
        }
        return result;
    }
    
    private void setConstraintViolations(ConstraintValidatorContext context) {
        context.disableDefaultConstraintViolation();
        context.buildConstraintViolationWithTemplate(messageTemplate)
                .addNode("password").addConstraintViolation();
        context.buildConstraintViolationWithTemplate(messageTemplate).addNode("passwordRepeat")
                .addConstraintViolation();
    }
    private boolean isValid(PasswordView value) {
        if(value == null){
            return true;
        }      
        return password.equals(value.getPasswordRepeat());
    }
}
the problem i faced is that PasswordViewValidator is executed before @PasswordContraint constraints (@Size and @NotBlank). It means that 
i got 2 errors when PasswordView = {password ='a' and passwordRepeat = 'b'} - the first error from @PasswordViewConstraint and the sec from @PasswordContraint.
I can force PasswordViewValidator to return true when password is null/blank or password length is less than 6 but i would like to avoid this kind of checking,  since it seems like a tight coupling between @PasswordConstraint internals (attribute value of composing annotation @Size) and PasswordViewValidator implementation. 
I can workaround by using GroupSequence to specy order between @PasswordConstraint and @PasswordViewConstraint but maybe someone has a better idea.
Thanks in advance.