Ordering groups of constraints

Constraints can be ordered in groups so that the application can control how value objects are validated. The Bean Validation provider is at liberty to evaluate constraints in any order that it pleases, regardless of which groups they belong to. In order to enforce control, the specification supplies the @javax.validation.GroupSequence annotation. The @GroupSequenceannotation defines the order of groups and informs the Bean Validation provider how to apply the constraints on a given group.

Let us look at an example of group sequence on another version of the address value object:

package je7hb.beanvalidation.cargroups;
import je7hb.beanvalidation.essentials.PostalCode;
import javax.validation.GroupSequence;
import javax.validation.constraints.*;
import javax.validation.groups.Default;

@PostalCodeSensitiveChecker(groups =
Address.AreaSensitive.class)
public class Address {
    @NotNull @Size(max = 50) private String street1;
    @Size(max = 50) private String street2;
    @NotNull @PostalCode private String postCode;
    @NotNull @Size(max = 30) private String city;

    public interface AreaSensitive {}

    @GroupSequence({AreaSensitive.class, Default.class})
    public interface Complete {}

    /* ... getters and setters ... */
}

The Address class defines two empty interfaces AreaSensitive and Complete. There is also a class-level constraint validator @PostalCodeSensitiveChecker, which verifies that the postal code property matches a specific location.

The group sequence on the nested interface Complete changes the order of validation to evaluate the AreaSensitive group before the Default group.

It is possible to refine the validation with the following unit test:

@Test
public void shouldValidateWithSpecificAreaOnly() {
Address addr = new Address();
addr.setPostCode("SW1 AA");
Set<ConstraintViolation<Address>> constraintViolations
= validator.validate(addr,
Address.AreaSensitive.class );
  assertEquals(0, constraintViolations.size());
}

The test method shouldValidateWithSpecificAreaOnly()evaluates against only the sensitive area by passing the interface group constraint class AreaSensitive. We pass the group constraint class to the validator's validate() method. We can evaluate the value object against the complete checker:

    @Test
    public void shouldValidateWithComplete() {
        Address addr = new Address();
        addr.setStreet1("1 Granger Avenue");
        addr.setCity("London");
        addr.setPostCode("SW1 3KG");
        Set<ConstraintViolation<Address>> constraintViolations
          = validator.validate(addr, Address.Complete.class );
        assertEquals(0, constraintViolations.size());
    }

The annotation @PostalCodeSensitiveChecker only permits postcodes starting with SW1. The Bean Validator provider, first, invokes constraints for the Complete group, which are then applied, and then it invokes the Default constraints. The provider will stop the evaluation chain of groups on the first constraint of a group that fails. This algorithm helps us to order a sequence of group validations based on how expensive the constraint verification is to run. We can, therefore, inform the Bean Validation provider to evaluate cheap constraint checks before the expensive ones like those that would make an imaginary relational database query.

Let's move on to how Bean Validation can help us check inputs and outputs of business service layer interfaces.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.138.105.215