Reputation: 7489
I've got a bean I'd like to do conditional validation on. For this purpose, I've defined a DefaultGroupSequenceProvider<MyObject>
which returns the list of groups to validate against.
Now, when validating an object that violates the constraints in more than one group in the sequence, only the first group with failures return it's result. I'd like to get an error on all violations, not just the ones in the first group with failures.
I'm thinking that this doesn't need a code-sample, but if I'm wrong, I'll be happy to provide one.
I followed this http://kh-yiu.blogspot.com/2014/04/conditional-bean-validation-using.html when creating the sequence. We use Spring if that matters.
Just a note, this works, in that it is impossible that an invalid bean will be reported as valid. But if the user has some input that breaks 3 constraints, and I return back 2 failures, the user will get another failure on the last field as soon as the first ones are corrected. Not exactly user-friendly.
Example:
Bean
@GroupSequenceProvider(BeanSequenceProvider.class)
public class MyBean {
@NotEmpty
private String name;
@NotNull
private MyType type;
@NotEmpty(groups = Special.class)
private String lastName;
// Getters and setters
}
Enum type
public enum MyType {
FIRST, SECOND
}
Provider
public class BeanSequenceProvider implements DefaultGroupSequenceProvider<MyBean> {
@Override
public List<Class<?>> getValidationGroups(final MyBean object) {
final List<Class<?>> classes = new ArrayList<>();
classes.add(MyBean.class);
if (object != null && object.getType() == MyType.SECOND) {
classes.add(Special.class);
}
return classes;
}
Group annotation
public interface Special {
}
Test class
public class MyBeanTest {
private static Validator validator;
private MyBean objectUnderTest;
@BeforeClass
public static void setUpOnce() throws Exception {
final ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
validator = validatorFactory.getValidator();
}
@Before
public void setUp() throws Exception {
objectUnderTest = new MyBean();
objectUnderTest.setName("Simen");
objectUnderTest.setType(MyType.FIRST);
objectUnderTest.setLastName("Woop");
}
@Test
public void testValid() throws Exception {
assertThat(validator.validate(objectUnderTest), is(empty()));
}
@Test
public void testMissingName() throws Exception {
objectUnderTest.setName(null);
assertThat(validator.validate(objectUnderTest), hasSize(1));
}
@Test
public void testMissingLastName() throws Exception {
objectUnderTest.setLastName(null);
assertThat(validator.validate(objectUnderTest), is(empty()));
objectUnderTest.setType(MyType.SECOND);
assertThat(validator.validate(objectUnderTest), hasSize(1));
objectUnderTest.setName(null);
assertThat(validator.validate(objectUnderTest), hasSize(2));
}
That very last assert fail, as there's one violation, not 2. As the constraint is violated in the default group, the Special
group is not violated.
Upvotes: 4
Views: 4473
Reputation: 19129
Ok, now I understand your question. The answer is that validation stops if there are one or more violations within a given group. To quote the spec:
Processing a group is defined in Section 4.6, “Validation routine” ; if one of the groups processed in the sequence generates one or more constraint violations, the groups following in the sequence must not be processed. This ensures that a set of constraint is evaluated only if another set of constraint is valid.
In your case there is a violation in the Default
group which means the Special
group is never validated.
Upvotes: 2