Red Hat

In Relation To Hibernate Validator

In Relation To Hibernate Validator

Now that Bean Validation is officially part of Java EE 6 and that Java EE6 is officially voted YES, let's see how Bean Validation integrates with the rest of the eco system.

What is Bean Validation

It's goal is to let application developers declare their data constraints once by annotating their model and make sure these constraints are validated by the different layers of the application in a consistent manner. Without Bean Validation, people have to write their validation rules in their favorite presentation framework, then in their business layer, then in their persistent layer, to some degree in the database schema and keep all of them synchronized.

Here is how this centralized constraint declaration looks like:

class User {
  @NotEmpty @Size(max=100)
  String getLogin() { ... }

  @NotEmpty @Size(max=100)
  String getFirstname() { ... }
  
  @Email @Size(max=250)
  String getEmail() { ... }
  ...
}

There are many more features like constraint composition, grouping but let's focus on how Bean Validation integrates with the EE 6 stack.

So what do I have to do to make it work in Java EE 6

The short answer is nothing. Not even an XML configuration trick.

Simply add your constraints on your domain model and the platform does the rest for you.

JSF and how to expose constraint violations to the user

In JSF, you bind form inputs to properties of your domain model. JSF 2 and Bean Validation smartly figure out which property you are binding to and execute the constraints associated to it.

<h:form id="register">
    <div style="color: red">
        <h:messages id="messages" globalOnly="true"/>
    </div>

    <div>
        Login:
        <h:inputText id="login" value="#{identifier.user.login}"/>
        <h:message style="color: red" for="login"/>
        <br/>
        Password:
        <h:inputSecret id="password" value="#{identifier.user.password}"/>
        <h:message style="color: red" for="password"/>
        <br/>
        Firstname:
        <h:inputText id="firstname" value="#{identifier.user.firstname}"/>
        <h:message style="color: red" for="firstname"/>
        <br/>
        Email:
        <h:inputText id="email" value="#{identifier.user.email}"/>
        <h:message style="color: red" for="email"/>
        <br/>

        <h:commandButton id="Login" value="Login" action="#{identifier.register}"/>
        <br/>
        <h:button id="cancel" value="Cancel" outcome="/home.xhtml"/>
    </div>
</h:form>

If the email, for example is malformed and the first name is left empty, Bean Validation will return the constraint violations to JSF 2 that will expose them to the user in a localized error message. By default, it just works and you don't even have to think about it.

For more advanced use cases, like disabling constraint validation for one or several fields or using a specific group or set of groups instead of the default one, you can use the <f:validateBean/> tag (check line 8 and 20 in the following example).

<h:form id="register">
    <div style="color: red">
        <h:messages id="messages" globalOnly="true"/>
    </div>

    <div>
        <!-- ***** use a specific group ***** -->
        <f:validateBean validationGroups="${identifier.validationGroups}">
            Login:
            <h:inputText id="login" value="#{identifier.user.login}"/>
            <h:message style="color: red" for="login"/>
            <br/>
            Password:
            <h:inputSecret id="password" value="#{identifier.user.password}"/>
            <h:message style="color: red" for="password"/>
            <br/>
            Firstname:
            <!-- ***** disable validation for firstname ***** -->
            <h:inputText id="firstname" value="#{identifier.user.firstname}">
                <f:validateBean disabled="true"/>
            </h:inputText>
            <h:message style="color: red" for="firstname"/>
            <br/>
            Email:
            <h:inputText id="email" value="#{identifier.user.email}"/>
            <h:message style="color: red" for="email"/>
            <br/>

            <h:commandButton id="Login" value="Login" action="#{identifier.register}"/>
            <br/>
            <h:button id="cancel" value="Cancel" outcome="/home.xhtml"/>
        </f:validateBean>
    </div>
</h:form>

In the future, we want to work with RichFaces so that the constraints declared on the object model are validated in the JSF components on the client side. This is something we had prototyped already and that Pete, Dan and I proposed to the JSF 2 expert group initially but we had to scale down our ambitions :) Expect some innovations from us in this area.

But not all your data comes from the presentation layer.

JPA 2: last line of defense

Again, by default, your JPA 2 provider runs Bean Validation on the entities you are about to persist or update. You are then guaranteed to not put invalid data in your database and thus increasing the quality of your data overall. Oh, and these are the same constraints you would have validated in JSF 2.0.

You can disable validation in JPA 2 using the validation-mode element in persistence.xml or the javax.persistence.validation.mode property and set them to none. More interestingly, you can chose which group will be validated upon entity persist, update and even delete operations. By default, the Default group is validated when you persist or update entities. Use any one of these properties to adjust that.

<property name="javax.persistence.validation.group.pre-persist" 
        value"javax.validation.groups.Default, com.acme.model.Structural"/>
<property name="javax.persistence.validation.group.pre-update" 
        value"javax.validation.groups.Default, com.acme.model.Structural"/>

<property name="javax.persistence.validation.group.pre-delete" 
        value"com.acme.model.SafeDestruct"/>

Hibernate Core and Hibernate Validator go a bit beyond that and propagate the constraints to the database schema (provided that you let Hibernate Core generate or update the schema for you). Simply set the hibernate.hbm2ddl.auto property to create, update or create-drop.

How about my service layer

You can inject a Validator or ValidatorFactory instance in any injectable POJO in Java EE 6.

class SalesService {
  @Inject Validator validator;
  @Inject @Current User user;

  public boolean canBuyInOneClick() {
    return validator.validate(user, BuyInOneClick.class).size() == 0;
  }

Where can I try it?

All of this is now available in JBoss AS 6 M1 that have just been released. Enjoy!

Hibernate Validator 4 unleashed

Posted by    |       |    Tagged as Bean Validation Hibernate Validator

After many months of polishing, we are happy to release Hibernate Validator 4. This is a major milestone for Hibernate Validator with tons of new features and a spec compliance.

For the newcomers

Hibernate Validator let's you declare constraints on your domain model using annotations like @NotNull or @Size and returns the list of constraint failures found in an object graph. Instead of duplicating constraint declarations in various application layers, constraints are centralized on your domain model and shared by all layers and frameworks: declared once, validate anywhere if you will.

What's new and cool?

Hibernate Validator is a complete rewrite and has many many many new features. Let me describe a handful of them:

  • constraint composition: a custom constraint can be composed of smaller constraints, avoiding code duplication, improving readability and increasing portability especially when combined with the set of built-in constraints.
  • groups: groups allow you to define a subset of the constraints you want to see validated at a given time. Useful in many situations like partially filled data, check the state of an object (can this user buy in one click?), order constraint validations. Oh and groups are not mere strings, they are a type-safe construct build on top of Java interfaces.
  • type-safe constraint declaration: Hibernate Validator 4 ensures that constraints set on a property are compatible with the property's type. This can even be theoretically checked at compile time.
  • more powerful custom constraints: as easy as before, more powerful than before. You can now customize the constraint violation messages reported by custom constraints and potentially return several violations if needed. A violation can point to a sub-property (useful for cross-property validations).
  • native integration with JPA 2 and JSF 2: Hibernate Validator 4 natively integrates with Java Persistence 2 and Java Server Faces 2 due to it's Bean Validation compliance. This integration is in the work in JBoss AS 5.2. People using Seam and Hibernate Core are already familiar with these style of integration since Hibernate Validator 3.
  • fluent type-safe bootstrap API: you can refine many aspects of Hibernate Validator like the message interpolation logic using the new bootstrap API.
  • metadata API: frameworks in need to query the constraints on a domain model can use the metadata API. This is for example used by Hibernate Core to propagate constraints to the database schema.
  • XML: XML configuration can be used in combination with or instead of annotations allowing for example redefinition of some constraints depending on the deployment environment.
  • a much improved test suite: we have completely rewritten the test suite which is now the base of the specification TCK.
  • compliance with JSR-303 Bean Validation: last but not least, Hibernate Validator 4 is the reference implementation, we couldn't make it more compliant ;) Practically, for you, it means you code against the specification API making your code more portable and your constraints will be visible by the whole Java ecosystem provided that they integrate Bean Validation (like Java EE 6 did for example).

Of course there are many other new features, check out the documentation here. You can download Hibernate Validator 4 from there and reach us in our forum.

The second good news is that the Bean Validation specification is now finished. I will hand it over to the JCP for final approval ballot today. More on that in a few days.

Many thanks to Hardy, the person behind Hibernate Validator 4's implementation for coping with last month/day/minute/second enhancements to the specification. A special thanks to Gunnar Morling and Alaa Nassef for their contribution despite a few administrative hiccups :)

Hibernate Validator 4.0.0 CR1

Posted by    |       |    Tagged as Hibernate Validator

The dust is settling around JSR-303 and we are happy to release Hibernate Validator 4.0.0.CR1. With this release we will be going into feature freeze, especially since we aligned it with JBoss AS 5.2 and Glassfish for integration.

Most of the work since Beta3 was spend on completing the Bean Validation TCK and ensuring that we cover all the assertions from the specification. We are really happy that we managed to create a TCK with readable and easy to understand tests. In fact, the TCK is an excellent source for usage examples. You can read more about the TCK on the Bean Validation TCK wiki page.

Regarding the actual changes to the Hibernate Validator codebase refer to the Jira release notes. From the changes listed there the following are worth mentioning seperately:

  • Hibernate Validator is now able to run in an environment with enabled SecurityManager (HV-171)
  • The package structure has changed from org.hibernate.validation to org.hibernate.validator
  • And the main Provider class name has changed from HibernateValidatorProvider to HibernateValidator

Refer to the Hibernate Validator Migration Guide to see what this means for you.

JBoss AS 5.2 beta is around the corner and it will have Bean Validation (Hibernate Validator) inside. Things are really coming together :)

Enjoy!

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]).

Bean Validation's public draft has now been approved by the EC (all members voting yes except Nortel and SpringSource who did not vote).

But we have not stopped there!

Reference implementation

We are pleased to release the first alpha of the Bean Validation Reference Implementation: Hibernate Validator 4 Alpha (download).

This is a big milestone and the core features are already present and the implementation is already used in the JSF 2.0 RI prototype. This release is not feature complete though, here are the main missing parts:

  • Group inheritance using interfaces or implicit grouping
  • Group sequence is implemented but not fully tested
  • Overriding the Default group of a class is not implemented yet
  • TraversableResolver does not integrates with JPA yet
  • XML configuration (META-INF/validation.xml)
  • XML mapping
  • some metadata APIs are not fully compliant
  • ConstraintValidatorContext is not operational

The distribution includes source code, jars and a getting started guide.

Everything should work as described in the spec otherwise. For help, come to our forum. Please file bugs to JIRA. For more informations on Hibernate Validator 4, see here. Many thanks to Hardy for leading the effort and to Alaa and Gunnar for stepping up.

Specification

This implementation is based on the specification 1.0 Beta3[1] (post public draft). This version improves:

  • the bootstrap API names are much more intuitive
  • type-safe validator implementations: a constraint is attached to several validators, the right one being chosen based on the targeted type
  • XML configuration via META-INF/valiation.xml
  • XML constraint mapping (allowing annotation overriding)

Give us feedback and tell us how it goes.

back to top