Help

Here is the latest draft before sending Bean Validation (JSR 303) to final stage (in pdf[1]). For the few who don't know yet ( ;) ), Bean Validation standardizes constraint declaration, definition, validation and metadata for the Java platform. Said otherwise, add an annotation to a property and hop it's validated.

class User {
   @NotEmpty @Size(max=50)
   String getName() { ... }

   @Email
   String getEmail() { ... }
}

Please give us last minute feedbacks in our forums

You can already use the spec as Hibernate Validator 4 implements it. Overall 38 coarse grained bugs and tasks got fixed or implemented respectively in this beta. Hibernate Validator artifacts can be downloaded on Sourceforge or in the JBoss Maven repository.

Back to the spec, let's discuss some of the enhancements.

A type-safe Path representation

A typesafe way to express navigation paths to the failing property has been added. Before, paths were expressed as strings like "addresses[0].street1" and libraries were forced to parse this string by hand. The Path object now exposes all individual nodes via the Iterable interface.

Here is the routine to build the old String based form.

StringBuilder stringPath = new StringBuilder();
Path path = constraintViolation.getPropertyPath();
boolean isRoot = true;
for(Node node : path) {
    // node with name
    if ( node.getName() != null ) {
        // likely a collection, add []
        if ( node.isInIterable() ) {
            stringPath.append("[");
            // list or array
            if ( node.getIndex() != null ) {
                stringPath.append( node.getIndex() );
            }
            // a Map
            else if ( node.getKey() ) {
                stringPath.append( node.getKey() );
            }
            stringPath.append("]");
        }

        //dot between properties
        if (isRoot) {
            isRoot = false;
        else {
            stringPath.append(".");
        }
        stringPath.append( node.getName() );
    }
}

Most usages are much much more simple and only involve using the node name.

The ConstraintValidatorContext used to customize error messages inside validators has a nice fluent API to add subnodes.

context.buildErrorWithMessageTemplate( "this detail is wrong" )
            .addSubNode( "addresses" )
            .addSubNode( "country" )
                .inIterable().atKey( "home" )
            .addSubNode( "name" )
            .addError();

Bootstrap API for provider specific usages

The bootstrap API now takes a Bean Validation provider class rather than the Configuration class to select a specific provider:

Validation.byProvider(HibernateValidatorProvider.class).buildValidatorFactory();

Opening doors for the future

While we unfortunately could not include method and parameter validations in this release, we have open the doors for provider specific extensions and potential standardization for the next revision of Bean Validation.

  • Built-in Constraint annotations can be hosted on parameters and constructors
  • unwrap allows access to provider specific extensions

Here is a possible implementation for Hibernate Validator (to be implemented ;) )

class AtYourService {
   doMeAFavor(@Valid Favor favor, @NotEmpty owner) { ... }
}

HibernateValidator hVal = validator.unwrap(HibernateValidator.class);
Set<ConstraintViolation> failures = hVal.validateMethod(doMeAFavor);

We have also added the notion of constraint payload. While ignored by Bean Validation and most Bean Validation providers, payloads can be used by validation clients to associate metadata to particular constraints. The use case driving this inclusion was to define a severity level to error messages.

class User {
   @NotEmpty(payload=Severity.ERROR) 
   @Size(max=50, payload=Severity.ERROR)
   String getName() { ... }

   @Email(payload=Severity.INFO)
   String getEmail() { ... }
}

This information can then be read by the presentation framework to display error messages differently. If you define constraints, don't forget the new mandatory payload parameter!

Various

We have also done various enhancements:

  • rethink java (sub)packages and move interfaces around
  • add support for unbound wildcards for ConstraintValidators
  • add support to return the list of ConstraintDescriptors matching a given set of groups
  • enhanced the TraversableResolver contract
  • rename message template keys to match f.q.c.NameOfTheConstraint.message (ie javax.validation.NotNull.message)

Many thanks to all the feedback received whether it be from within and outside the JCP. Feel free to drop more last minute feedbacks in our forums, and try Hibernate Validator 4!

PS: this draft was supposed to go through the regular JCP process but due to legal dirty work at play, this is not currently possible (I might expand on the subject in a different post depending on how frustrated I end up being). Our legal team is at work but in the mean time, I wanted to give you the premium (download the spec here[1]).