The public draft of Bean Validation is finally out and available here on the JCP website. We have made a lot of improvements and took a lot of feedback from you since the last draft:
- interface-based groups
- constraint composition
- built-in constraints
- multiple reports per constraint violation
- bootstrap API
- method level validation
- integration with JPA, JSF and Java EE
Please go check the spec and give us your feedback in our forum. We plan to get a final spec early february, so don't delay :)
Groups
The fundamental notion of group is basically unchanged but it has morphed into a much more type-safe and cleaner beast. Instead of declaring groups as strings, groups are now interfaces. This has several advantages including:
- easier to find a group usage in IDEs
- errors due to typos will be visible at compilation time rather than runtime
- groups can inherit from each other using the natural interface inheritance model. This allows group composition.
- partial validation based on interfaces hosting constraint definitions
/** * Customer can buy bypassing the harassing checking process * * @author Emmanuel Bernard */ public interface BuyInOneClick extends Default, Billable {} /** * User representation */ public class User { @NotNull private String firstname; @NotNull(groups = Default.class) private String lastname; @NotNull(groups = {Billable.class}) private CreditCard defaultCreditCard; } Set<ConstraintViolation> violations = validator.validate(user, BuyInOneClick.class);
The spec is very readable and has a lot of real-life examples, check section 3.4.
Constraints
Constraints can now declaratively be composed of more primitive constraints. This both helps to reduce code duplication and to allow primitive constraints to be exposed in the metadata and used by tools like JavaScript generators.
@Numerical @Size(min=5, max=5) @ConstraintValidator(FrenchZipcodeValidator.class) @Documented @Target({ANNOTATION_TYPE, METHOD, FIELD}) @Retention(RUNTIME) public @interface FrenchZipCode { String message() default "Wrong zipcode"; Class<?>[] groups() default {}; }
I described the idea in more details in this previous blog entry.
Speaking of constraint definition, the specification now comes with a set of built-in constraints: @Null, @NotNull, @AssertTrue, @AssertFalse, @Min, @Max, @Size, @Digits, @Past, @Future. These are the fundamental bricks that can be understood by all tools accessing metadata.
Finally, constraint implementations can now raise more than one violation report per constraint. This is particularly useful when a bean-level constraint is targeting two specific properties.
@CheckAddressConsistency public class Address { private String zipCode; private String city; }
@CheckAddressConsistency probably wants to raise two violation reports, one targeting zipCode and one targeting city. This is also useful to define fine grained error messages depending on the failure. See section 2.4 for more info.
API
The Validator interface can now validate any type of object and is no longer tied to a given JavaBean type.
Validator validator = validatorFactory.getValidator(); Set<ConstraintViolation<Address>> addressViolations = validator.validate(address); Set<ConstraintViolation<User>> userViolations = validator.validate(user);
The specification has a bootstrap API letting you customize various validation components and optionally letting you choose the specific Bean Validation provider you seek. An older version of the bootstrap API is described in this blog entry, the latest version is of course available in the spec section 4.4.
In appendix, you will find a proposal for method level validations: parameter and returned values can be decorated with constraints declarations. This feature has been widely requested, let us know what you think.
Integration
The JPA, JSF and Java EE integration proposals are also available in appendix.
Thanks to everyone for your past feedback and your future one :)