Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Bean Validation: GroupSequence with Class-Level Constraint

I have a bean class with multiple (custom) inner constraints and one class-level constraint. I'd like to validate the inner constraints before the class-level constraint. The code looks like this:

@GroupSequence({ Inner.class, NewSlotBean.class })
@TotalBeanValid(groups = NewSlotBean.class)
public class NewSlotBean {

    @DayMonthYearString(groups = Inner.class)
    private String slotDay;

    @TimeString(groups = Inner.class)
    private String slotBegin;

    @LengthString(groups = Inner.class)
    private String slotLength;
}

(Inner is just an empty interface lying around somewhere).

However, when I try to run this, the class-level constraint does not get validated at all. When I try to define the GroupSequence like

@GroupSequence({ Inner.class, Outer.class })

(with Outer being a random interface), I get the exception:

javax.validation.GroupDefinitionException: ...*.beans.NewSlotBean must be part of the redefined default group sequence.

Does s/o know how to make sure that the class-level constraint is validated after the inner ones? (This appears not to be the default! I've had random problems with it popping up after a while.)

like image 612
Hinton Avatar asked Apr 30 '12 07:04

Hinton


People also ask

What interface must you implement when you require class level validation?

The validation class implements the ConstraintValidator interface, and must also implement the isValid method; it's in this method that we defined our validation rules.

How do you validate constraints?

The VALIDATE CONSTRAINT statement is part of ALTER TABLE and checks whether values in a column match a constraint on the column. This statement is especially useful after applying a constraint to an existing column via ADD CONSTRAINT .

What is the difference between @valid and @validated?

The @Valid annotation ensures the validation of the whole object. Importantly, it performs the validation of the whole object graph. However, this creates issues for scenarios needing only partial validation. On the other hand, we can use @Validated for group validation, including the above partial validation.


1 Answers

Try this:

@GroupSequence({ Inner.class, NewSlotBean.class })
@TotalBeanValid(groups = Default.class)
public class NewSlotBean {

    @DayMonthYearString(groups = Inner.class)
    private String slotDay;

    @TimeString(groups = Inner.class)
    private String slotBegin;

    @LengthString(groups = Inner.class)
    private String slotLength;
}

According to the spec NewSlotBean is just a stand-in for the default group. See also section 3.4.3 of the Bean Validation spec:

Since sequences cannot have circular dependencies, using Default in the declaration of a sequence is not an option. Constraints hosted on a class A and belonging to the Default group (by default or explicitly) implicitly belong to the group A.

A sequence defined on a class A (i.e. redefining the Default groups for the class) must contain the group A. In other words, the default constraints hosted on a class must be part of the sequence definition. If a @GroupSequence redefining the Default group for a class A does not contain the group A, a GroupDefinitionException is raised when Constraint declaration and validation process the class is validated or when its metadata is requested.

like image 110
Hardy Avatar answered Oct 22 '22 14:10

Hardy