GroupSequence and ordered evaluation in JSR 303
In our application we have such a case:
- Constraints should be evaluated in particular order. (cheap to expensive)
- Constraints should not be evaluated after a violation per field.
- All fields should be validated.
For first two, groupsequence is fitting very good. However for my 3rd requirement I could not find a way to solve.
public class AccountBean开发者_开发技巧 {
@CheepValidation
@ExpensiveValidation
@VeryExpensiveValidation
private String name;
@CheepValidation
@ExpensiveValidation
@VeryExpensiveValidation
private String surname
}
For example,
Let's say that, for name field VeryExpensiveValidationconstraint is violated and for surname field ExpensiveValidation constraint is violated.
For this case I should display:
For field name: Only VeryExpensiveValidation error message For field surname: Only ExpensiveValidation error message
Note that for field surname we did not evaluate VeryExpensiveValidation constraint.
Is there a way to implement it with JSR 303?
Thanks
You can use groups and @GroupSequence, but it's a bit unwieldy.
public class AccountBean {
@CheapValidation(groups=Name1.class)
@ExpensiveValidation(groups=Name2.class)
@VeryExpensiveValidation(groups=Name3.class)
String name;
@CheapValidation(groups=Surname1.class)
@ExpensiveValidation(groups=Surname2.class)
@VeryExpensiveValidation(groups=Surname3.class)
String surname;
public interface Name1 {}
public interface Name2 {}
public interface Name3 {}
@GroupSequence({Name1.class, Name2.class, Name3.class})
public interface Name {}
public interface Surname1 {}
public interface Surname2 {}
public interface Surname3 {}
@GroupSequence({Surname1.class, Surname2.class, Surname3.class})
public interface Surname {}
}
Then validate with:
validator.validate(myAccountBean,
AccountBean.Name.class, AccountBean.Surname.class)
The key is to have two entirely independent group sequences.
Unfortunately, it seems you must explicitly list the groups for all the fields you want to validate. I wasn't able to get it working with a 'default' @GroupSequence. Can anyone improve on this?
I've implemented ordered validation with GroupSequence but, generally speaking, GroupSequence beans validation implementation is not transparent.
Meaning, untill first group is fully validated, you can not trigger the validation of the second group.
E.g.
I have 3 validated fields with custom validators. The idea is pretty straightforward: every field should be validated with the set of validators from top to bottom independently (descending cardinality).
@StringPropertyNotNullOrEmptyConstraint(message = "Group name is required", groups = {ValidationStep1.class})
private final StringProperty groupName;
@StringPropertyNotNullOrEmptyConstraint(message = "Group password is required", groups = {ValidationStep1.class})
@StringPropertyMatchConstraint(message = "The given password phrases do not match", dependentProperties = {"groupPasswordMatch"}, groups = {ValidationStep2.class})
private final StringProperty groupPassword;
@StringPropertyNotNullOrEmptyConstraint(message = "Group password match is required", groups = {ValidationStep1.class})
@StringPropertyMatchConstraint(message = "The given passwords phrases do not match", dependentProperties = {"groupPassword"}, groups = {ValidationStep2.class})
private final StringProperty groupPasswordMatch;
public interface ValidationStep1 {
}
public interface ValidationStep2 {
}
@GroupSequence({GroupDialogModel.class, ValidationStep1.class, ValidationStep2.class})
public interface GroupDialogModelValidationSequence {
}
ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
Validator validator = validatorFactory.getValidator();
Set<ConstraintViolation<GroupDialogModel>> constraintViolations = validator.validate(this, GroupDialogModelValidationSequence.class);
The caveat of this approach is that each field should go through ValidationStep1 first and only after each validation of step 1 succeeds it goes to step 2. For example, even if password fields are not empty, but contain different values, validation for them succeeds if group name field does not contain any value. And only after I enter some value to the group name, ValidationStep1 group succeeds and then it displays validation result of ValidationStep2 (passwords do not match).
Making each group for each field in every sequence is bad practice IMHO, but it seems like there is no other choice.
Any other solution is much appreciated.
精彩评论