We have a use case in which we have a fairly poorly constructed bean that contains fields like so:
public class DataBean {
private boolean flag1;
private boolean flag2;
private String phone1;
private String address1;
private String city1;
private String state1;
private String phone2;
private String address2;
private String city2;
private String state2;
}
We need to validate phone/address/city/state [1|2] only if flag [1|2] is true. Bad, bad design, granted.
Our current strategy is to use @NotNull (or whatever validations we need) on each of the "real" data fields, and use a groups indicator, like so:
public class DataBean {
private boolean flag1;
private boolean flag2;
@NotNull(groups = Info.First.class)
private String phone1;
@NotNull(groups = Info.First.class)
private String address1;
@NotNull(groups = Info.Fir开发者_开发知识库st.class)
private String city1;
@NotNull(groups = Info.First.class)
private String state1;
@NotNull(groups = Info.Second.class)
private String phone2;
@NotNull(groups = Info.Second.class)
private String address2;
@NotNull(groups = Info.Second.class)
private String city2;
@NotNull(groups = Info.Second.class)
private String state2;
}
In our business logic where we are validating this bean (which has various other fields in it that will be validated by the "default" validation group), we will get violations for the "default" group, then check if flag1 is true, if so, run validations for Info.First.class, check if flag2 is true, then run validations for Info.Second.class.
Now the question ... is there any way of hooking into these groups from a custom class validator? I'm envisioning having a class validator that takes the flag1/flag2 properties and their corresponding custom groups and when isValid is invoked, it does these secondary/tertiary calls for the groups. The purpose being, simply, that the custom class validator would be in the default group, so the business logic validating this class wouldn't have the details of this ugly legacy design leak into it by virtue of having to call the validation separately.
Thoughts? Thanks!
I'm not entirely certain I've grasped what problem you are trying to solve. My interpretation is that are trying to avoid explicitly making separate calls for each validation group but call the two non default groups according to the flags? Can not just define some group sequences and use these instead of the flags? Group sequences are used in the same way as groups. The only thing about them is that they will stop validating the groups if one group fails.
If you need to validate always validate all of the groups according to the flags, the your custom class validator can call groups()
on the constraint annotation passed into its initialize method.
Make a class level validator and initialize the validator inside it. You can then validate the object by groups inside the main valid method of the class level constraint by adding constraint exceptions on each field. See below:
Constraint interface:
@Documented
@Constraint(validatedBy = {DataBeanValidator.class})
@Target({METHOD, FIELD, ANNOTATION_TYPE, TYPE})
@Retention(RUNTIME)
public @interface DataBeanConstraint {
String message() default "validation.dataBean";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Validator:
public class DataBeanValidator implements ConstraintValidator<DataBeanConstraint, DataBean> {
private Validator validator;
@Override
public void initialize(DataBeanConstraint constraintAnnotation) {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Override
public boolean isValid(BeanData beanData, ConstraintValidatorContext context) {
if (beanData == null) {
return true;
}
if (beanData.isFlag1) {
Set<ConstraintViolation<DataBean>> constraintViolations = validator.validate(beanData, Info.First.class);
if (constraintViolations != null) {
for (ConstraintViolation<BeanData> constraintViolation : constraintViolations) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("required field").
addNode(constraintViolation.getPropertyPath().toString())
.addConstraintViolation();
}
}
}
}
}
Class level validator:
@DataBeanConstraint
public class DataBean {
private boolean flag1;
private boolean flag2;
@NotNull(groups = Info.First.class)
private String phone1;
@NotNull(groups = Info.First.class)
private String address1;
@NotNull(groups = Info.First.class)
private String city1;
@NotNull(groups = Info.First.class)
private String state1;
@NotNull(groups = Info.Second.class)
private String phone2;
@NotNull(groups = Info.Second.class)
private String address2;
@NotNull(groups = Info.Second.class)
private String city2;
@NotNull(groups = Info.Second.class)
private String state2;
}
精彩评论