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.