Red Hat

In Relation To Hibernate Validator

In Relation To Hibernate Validator

I am happy to announce Hibernate Validator 5.1.0.CR1, hopefully (fingers crossed) the last release prior Final. We used the release for last adjustments and some bug fixes.

On the bug fix side, we addressed issues with the CDI integration (HV-858), EL message interpolation (HV-834) and validated value unwrapping in conjunction with Validator#validateValue and Validator#validateProperty (HV-860).

We also gave @Mod10Check and @Mod11Check a final overhaul and made the parameter naming more consistent and changed the semantics of startIndex, endIndex and checkDigitIndex. They are now all inclusive and always relative to the original validated value, indepent of ignoreNonDigitCharacters. If you are already using these new constraints, I recommend you review the linked Javadocs to understand the updated semantics.

Last but not least, we added yet another checksum related constraint - @EAN. It allows you to validate International Article Numbers (EAN-13 and EAN-8).

The full change log can be found here. Maven artefacts are on the JBoss Maven repository under the GAV org.hibernate:hibernate-validator:5.1.0.CR1 and distribution bundles are available on SourceForge.

Feedback and questions are always welcome via the Hibernate Validator forum or on stackoverflow using the hibernate-validator tag.

Enjoy!

It has been a while since the first alpha release of Validator 5.1, but as the saying goes: Haste makes waste :-) There is a lot going on in the Hibernate universe and over the last few months we have been especially busy with projects like Search and OGM. Not to speak of the new Hibernate website. Sigh, if we just had more contributors lending a hand (hint, hint).

Nevertheless, we found time to also work on Validator and the result is Hibernate Validator 5.1.0.Beta1 with some nice new features and bug fixes. The most notable feature is the introduction of @UnwrapValidatedValue and the corresponding ValidatedValueUnwrapper SPI (see HV-819). The idea is that in some cases the value to validate is contained in a wrapper type and one would have to add custom ConstraintValidator implementations for each constrained type and constraint. Think Java 8 Optional or JavaFX Property types. For example in JavaFX you could have:

@NotBlank
@UnwrapValidatedValue
private Property<String> name = new SimpleStringProperty( "Foo" );
Here the intention is to apply the @NotBlank constraint to the string value, not the the Property instance. By annotating name with @UnwrapValidatedValue the Validator engine knows that it has to unwrap the value prior to validation. To be able to do this, you need to also register an implementation of ValidatedValueUnwrapper which specifies how this unwrapping has to happen. You can do this via validation.xml as provider specific property (hibernate.validator.validated_value_handlers) or programmatically via:
Validator validator = Validation.byProvider( HibernateValidator.class )
        .configure()
        .addValidatedValueHandler( new PropertyValueUnwrapper() )
        .buildValidatorFactory()
        .getValidator();
PropertyValueUnwrapper is in this case an implementation of ValidatedValueUnwrapper which tells the Validator engine how to unwrap a Property type and of which type the validated value is. The latter is needed for constraint validator resolution. For more information refer to the online documetnation.

What else is worth mentioning? Thanks to Brent Douglas for profiling of Hibernate Validator and detecting of some potential memory leaks - see HV-838 and HV-842. They are fixed now.

Thanks also to Victor Rezende dos Santos and Shin Sang-Jae. Victor found a problem with the Brazilian CPF constraint which lead to its refactoring HV-808, as well as the deprecation of @ModCheck and the introduction of dedicated @Mod10 and @Mod11 constraints as replacements. Shin on the other hand provided a Korean translation of the ValidationMessages properties bundle.

Last but not least, we also have an improved the memory footprint by reducing the amount of memory consumed by metadata (HV-589).

In total 29 resolved issues. Not bad in my opinion and definitely worth upgrading to Validator 5.1.

Maven artefacts are on the JBoss Maven repository under the GAV org.hibernate:hibernate-validator:5.1.0.Beta1 and distribution bundles are available on SourceForge. Send us feedback either via the Hibernate Validator forum or on stackoverflow using the hibernate-validator tag.

Enjoy!

Emmanuel is headed to JavaOne, where you can see his hands-on presentations: live on stage coding showing the latest features of Hibernate Search and Bean Validation. It's a unique experience to see how easy it is to get started with these technologies, and also what powerful features they can provide you in just one hour coding.

Hibernate Search: Geolocalized Search in Java EE 7 in 59 Minutes

Full link: Geolocalized Search in Java EE 7 in 59 Minutes with Hibernate Search [BOF3307]

Abstract:

Search is passé; we need Foursquare-style location and should let people search in specific vicinities. And no, you don’t have to leave Java or JavaEE to make this a breeze. This session shows you how to boost your existing applications by easily adding full-text search, spatial search, faceting, and even all at the same time! Faceted results return the list of results as well as their count by category—price range, brand, colour, and so on. This session takes an existing JavaEE7–based application and adds search services via Hibernate Search. It favours code and step-by-step IDE work over slides.
  • Presenter: Emmanuel Bernard
  • Location Parc 55 - Mission
  • Time: Monday, Sep 23 7:30 PM - 8:15 PM

Bean Validation: What Does It Look Like in Practice?

Full link: Bean Validation: What Does It Look Like in Practice? [CON3368]

Abstract:

Java EE 7 is a very rich environment. This session takes you on a practical code-driven Bean Validation walk-through: how to use it in your applications and what not to do—all with an example-driven approach. The presentation gradually adds constraints and validations to an existing application and examines many features, both old and new, including constraint declaration, custom constraint, method validation, EL-based message interpolation, JAX-RS integration, and many more. It spends as much time as possible in the IDE. No previous knowledge of Bean Validation is required.
  • Presenter: Emmanuel Bernard
  • Location: Parc 55 - Cyril Magnin II/III
  • Time: Wednesday, Sep 25 11:30 AM - 12:30 PM

Other JBoss technologies at JavaOne

There are lots of speakers from the JBoss community at JavaOne, see the dedicated website!

With the release of Hibernate Validator 5.1.0.Alpha1 just out, it is time to pick up on the Bean Validation 1.1 spotlight series and cast a light onto method validation. Long time Hibernate Validator users know that method validation is part of Validator since version 4.2, however only as a provider specific featue. Bean Validation 1.1 makes method validation now part of the specification.

But what is method validation? Method validation is the ability to place constraint annotations onto methods or constructors and/or their parameters. Here is an example:

public class User {
     public User(@NotNull @Size(max = 40) String firstName, @NotNull @Size(max = 40) String lastName) {
        // ...
     }

     @NotNull
     @Valid
     public Order placeOrder(@NotNull @Valid Item item) {
          // ...
     }

     @PasswordsMatch
     public void resetPassword( @NotNull String password, @NotNull String passwordConfirmation) {
          // ...
     }

     // ...
}

The constraints describe that whenever the constructor of User is called, firstName and lastName cannot be null and neither can exceed 40 characters. Also, whenever the user places an order, the provided Item instance cannot be null and must be valid. Valid in this context means that the instance itself passes the validation of all its property (constraints placed on fields and getters) and class level constraints. The returned Order instance of the placeOrder() call is a non null instance which also passes all bean constrains for this type. Last but not least, if the user resets his password, the new password and the password confirmation cannot be null and they have to match. The latter is expressed via a so called cross parameter constraint - @PasswordMatch.

Overall, the shown constraints define the pre- and postconditions for a given method or constructor call. This is commonly known as programming by contract which allows to make the specification of the these constraints part of the method. It also avoids code duplication, since these checks don't have to be implemented redundantly in the body of the methods.

But how do these constraints get validated then? Bean Validation offers for this purpose ExecutableValidator which can be retrieved from a Validator instance via Validator.forExecutables(). This ExecutableValidator offers the methods to validate method/constructor parameters and return values. This in itself, however, is not very helpful for an application developer. She would have to write the required code to handle the validation herself which is not a trivial task. Instead the intention is that frameworks and libraries provide the integration for the application developer via some sort of AOP, interceptor or proxy based approach. That way, method validation occurs transparently upon invocation of constrained methods or constructors, throwing a ConstraintViolationException whenever one more more constraints are violated. An example of this type of integration is the Java EE 7 framework.

In Java EE 7 all CDI managed beans are automatically method validated. All you have to do is to place constraints on methods or constructors and their parameters. CDI will then, via its interceptor capabilities, evaluate all method validation constraints. In this context it is important to know that Bean Validation does not validate getters (method name starts with get, has a return type and no parameters or starts with is, is returning boolean and has no parameters) per default. This is to avoid conflicts with the validation of bean constraints. This behaviour can be configured via the use of @ValidateOnExecution or in validation.xml using default-validated-executable-types. The specification contains all the details and also gives some examples.

Last but not least, another caveat. When using method validation constraints within class hierarchies, the specification demands that the Liskov substitution principle holds. Formally this means that a method's preconditions (as represented by parameter constraints) must not be strengthened and its postconditions (as represented by return value constraints) must not be weakened in sub-types. Concretely it implies that in sub-types no parameter constraints can be declared on overridden or implemented methods. Also parameters cannot be marked for cascaded validation. Instead, all parameter constraints must be defined at the method's root within the hierarchy. The Bean Validation implementation will throw a ConstraintDeclarationException if the Liskov substitution principle is violated. The complete set of rules can be found in Method constraints in inheritance hierarchies of the specification.

I hope this blog helped to shine some light on the biggest new feature of Bean Validation 1.1 - method validation. If you have questions, leave a comment, contact us via the forum or chat to us in IRC.

Happy validating!

P.S. We will talk about the changes to the metadata and javax.validation.Path API related to method validation in another post. We also will have a closer look at the details of implementing cross parameter constraints. Stay tuned.

It's my pleasure to announce the first alpha release of Hibernate Validator 5.1. This release brings you several new features based on top of the Bean Validation 1.1 APIs, substantial performance improvements as well as some bug fixes.

As usual, you can obtain this release either as distribution bundle (ZIP or TAR.GZ) from SourceForge or retrieve it using your preferred dependency management tool under the GAV coordinates org.hibernate:hibernate-validator:5.1.0.Alpha1. The binaries have been pushed to the JBoss Maven repository and should soon be synched to Maven Central as well.

What's in it?

The features added in this release are centered around the new APIs and functionality provided by Bean Validation 1.1, such as method validation and expression based message interpolation. Let's have a closer look at some of them.

With HV-714 we added a new constraint, @ParameterScriptAssert which allows to validate the parameters of a method or constructor using a script expression:

@ParametersScriptAssert(script = "arg0.before(arg1)", lang = "javascript")
public void createCalendarEvent(Date start, Date end, String title) { ... }

Similar to @ScriptAssert (which applies to the class level) this constraint can be used with every scripting language for which a JSR 223 compatible engine exists. You can choose between a wide variety of options such as JavaScript (for which the JDK provides an engine out of the box), Groovy, JRuby and many others.

As shown in the example, the names arg0, arg1 etc. are used by default to refer to the parameters of the validated method or constructor. This does not read very well, but unfortunately Java doesn't provide a standardized way to obtain parameter names at runtime (this will change with Java 8 where parameter names can be accessed via reflection).

To address this issue, Bean Validation defines an SPI which allows to plug in custom parameter name providers. Hibernate Validator offers now an implementation of that SPI (HV-802) which is based on the ParaNamer project. ParaNamer is a nice little library which provides several ways for obtaining parameter names at runtime:

  • based on debug symbols created by the Java compiler,
  • constants with the parameter names woven into the bytecode in a post-compile step or
  • annotations such as the @Named annotation from JSR 330.

To use this parameter name provider, add the ParaNamer library to the classpath and configure the provider like this when bootstrapping a validator:

Validator validator = Validation.byDefaultProvider()
    .configure()
    .parameterNameProvider( new ParanamerParameterNameProvider() )
    .buildValidatorFactory()
    .getValidator();

With the parameter name provider configured, you can refer to the parameters using their actual names from within the @ParameterScriptAssert constraint (the names will also be used by constraint violations for invalid parameter constraints):

@ParametersScriptAssert(script = "start.before(end)", lang = "javascript")
public void createCalendarEvent(Date start, Date end, String title) { ... }

Refer to the ParaNamer documentation to learn more about the different ways it provides for accessing parameter names.

Message interpolation

Another nice new feature is an extension of the ConstraintValidatorContext API which allows to add arbitrary objects to constraint violation messages (HV-701). As an example, let's consider this custom validator for the @Future constraint:

public class MyFutureValidator implements ConstraintValidator<Future, Date> {

    public void initialize(Future constraintAnnotation) {}

    public boolean isValid(Date value, ConstraintValidatorContext context) {
        if ( value == null ) { return true; }

        Date now = GregorianCalendar.getInstance().getTime();

        if ( value.before( now ) ) {
            HibernateConstraintValidatorContext hibernateContext =
                context.unwrap( HibernateConstraintValidatorContext.class );

            hibernateContext.disableDefaultConstraintViolation();
            hibernateContext.addExpressionVariable( "now", now )
                .buildConstraintViolationWithTemplate( 
                    "Must be after ${formatter.format( '%1$te.%1$tm.%1$tY %1$tH:%1$tM', now ) }"
                )
                .addConstraintViolation();

            return false;
        }

        return true;
    }
}

Instead of just using "Must be in the future" as constraint violation message, this validator adds the current time to the message. For that purpose an expression variable with the name "now" is added to the validation context, holding a Date object representing the current time. Using the variable name, it can be accessed from within the violation message and formatted as shown in the example.

Performance improvements

Besides adding new functionality, we also worked hard to make sure that Hibernate Validator gives you the performance you deserve. Throughout extensive profiling sessions we identified and addressed several performance bottlenecks, e.g. around message interpolation (HV-637). Performance tuning - with respect to memory consumption as well as execution speed - is an ongoing effort and you can look forward to further improvements in that area in the next releases.

This concludes our tour through the new features of Hibernate Validator 5.1.0.Alpha1. You can find the complete list of all fixed issues in the release notes. The reference guide describes all added functionality in detail.

Let us know how you like the new release by adding a comment or posting to the forum. If you have found a bug be sure to file a JIRA issue for it. Or, even better, fork the code base and submit a pull request with the required fix. To discuss any development related issues, just send a message to the hibernate-dev list.

It has been a couple of weeks since Bean Validation 1.1 has gone final. In the mean time, the Java EE 7 platform spec has been finalized as well, so it's about time to have a closer look at what you can expect from these updates in relation to Bean Validation and its reference implementation, Hibernate Validator 5.

Over the following weeks, we'll dive into the most exciting new features in a series of blog posts, starting today with the usage of expression language in error messages.

Executive summary

Many users relate the Unified Expression Language (EL) only to JSF and JSP. But it doesn't stop there. Actually, EL has matured over time into an independent language with it's own specification and nice features such as Lambda expressions. It can be used in any application layer, in Java EE as well as Java SE based applications.

Bean Validation 1.1 makes use of EL to offer advanced functionality around constraint violation messages such as conditional messages and customizable message formatting.

Using EL expressions in constraint messages

As an example, let's take a look at the built-in @DecimalMax constraint. As of Bean Validation 1.1, this constraint has a new flag named inclusive which specifies whether the given maximum value is inclusive or not. Depending on the flag's value, the constraint's error message should either be must be less than {value} or must be less than or equal to {value}.

This kind of behaviour was not easily achievable in Bean Validation 1.0 but it is straight-forward using an EL expression which conditionally adds the or equal to part:

must be less than ${inclusive == true ? 'or equal to ' : ''}{value}"

EL expressions are given in the form ${expression}. You can use them to implement conditional logic as in the example, perform calculations, nicely format values etc. Refer to the EL specification to learn more about the provided functionality and the syntax.

As the {value} expression from the example shows, the Bean Validation 1.0 syntax for referencing attributes is still supported and takes precedence over expression evaluation. So for instance the message ${amount} would be interpolated into something like $50.

Referring to the validated value

Besides all attributes of the validated constraint (such as inclusive) you can access the value to which the constraint is applied using the name validatedValue as shown in the following example:

@ValidCustomer( message = "Not a valid customer: ${validatedValue.getName()}" )
public class Customer {

    //...

    public String getName() {
        return name;
    }
}

Here, a violation of the @ValidCustomer constraint would produce a message such as Not a valid customer: Bob.

Doing some formatting

Finally, a helper for formatting strings is exposed under the name formatter, providing a var-args method format(String format, Object... args) which exactly behaves like java.util.Formatter.format(String format, Object... args). This comes in handy if you e.g. want to format number values in a special way:

public class Order {

    @DecimalMin(value="20.00", message="Order value too low: € ${formatter.format('%08.2f', validatedValue)}")
    private final BigDecimal value;

    //...
}

The shown format expression causes the value to be padded with leading zeros, so if the @DecimalMin constraint is violated, you would get a message such as Order value too low: € 00017.89.

EL and the classpath

In order to use the expression language feature, you need an EL implementation on your classpath. That's usually the case when running in a Java EE container such as WildFly, but you'll have to add an implementation by yourself if your application runs in a plain Java SE environment. Two implementations known to work with Hibernate Validator are the EL reference implementation and JUEL.

Finally a special tip to all the Tomcat users out there. Hibernate Validator requires at least EL 2.2. This is part of Tomcat 7, so you should be all set there. Tomcat 6 only comes with an EL 2.1 implementation, though. So does this mean you can't experience all the Bean Validation 1.1 goodness on Tomcat 6 then? Luckily not, it just requires a little preparation. Check out the Hibernate Validator FAQ to learn how to update the Tomcat EL libraries.

Trying it out yourself

If you'd like to give the expression language feature a spin, just grab the latest Hibernate Validator release from here. If you work with Maven, Gradle or similar, you can pull it into your project using its GAV coordinates org.hibernate.hibernate-validator.5.0.1.Final. And if you feel adventurous and like playing with the latest bits, you even may build WildFly yourself from its sources. It has been updated to Hibernate Validator 5 a couple of days ago.

The recently revamped reference guide has all the information you need, and we're happy to help you with any questions in the forum.

Today we are happy to announce the 5.0.1.Final release of Hibernate Validator. In case you are wondering what happened with 5.0.0.Final - it has not gone missing. In fact it was released on the 11th of April.

The long story is, that we had to release 5.0.0.Final to meet the Java EE 7 release schedule. At the time the functionality was complete, but documentation was not. Given the amount of changes introduced by Bean Validation 1.1, we felt it was important to wait with the announcement of Hibernate Validator 5 until the documentation is up to scratch. That's the case with 5.0.1.Final. Not only does this release offer a complete Bean Validation 1.1 implementation it also includes an updated online documentation.

The highlights of Hibernate Validator 5 are (with pointers into the freshly baked documentation):

  • Standardized method validation of parameters and return values. This has been a Hibernate Validator 4 specific functionality, but got now standardized as part of Bean Validation 1.1.
  • Integration with Context and Dependency Injection (CDI). There are default ValidatorFactory and Validator instances available and you can now use @Inject in ConstraintValidator implementations out of the box. Requested custom implementations (via validation.xml) of resources like ConstraintValidatorFactory, MessageInterpolator, ParameterNameProvider or TraversableResolver are also provided as managed beans. Last but not least, the CDI integration offers transparent method validation for CDI beans.
  • Group conversion
  • Error message interpolation using EL expressions

We are also planning to create a little blog series introducing these new features in more detail. Stay tuned!

For now have a look at the Getting Started section of the documentation to see what you need to use Hibernate Validator 5. Naturally you will need the new Bean Validation 1.1 dependency, but you will also need an EL implementation - either provided by a container or added to your Java SE environment. Additional migration pointers can also be found in the Hibernate Validator migration guide.

You find the full release notes as usual on Jira. Maven artefacts are on the JBoss Maven repository under the GAV org.hibernate:hibernate-validator:5.0.1.Final and distribution bundles are available on SourceForge.

We are looking forward to get some feedback either on the Hibernate Validator forum or on stackoverflow using the hibernate-validator tag.

Enjoy!

Bean Validation, Hibernate Validator (its Reference Implementation) and the Test Compatibility Kit have been handed over to the JCP for what is called the Final Approval Ballot. That's when the expert committee votes for the go / no-go of the specification going final as it is.

We have found a few glitches when working on both the RI and the TCK in the last month but everything is in order now. The biggest visible change for you is that we renamed @ValidateExecutable into @ValidateOnExecution and we added a way to disable method validation entirely via the XML deployment descriptor.

We worked hard to make a stellar TCK. Let's speak numbers: the specification has 549 assertions including 492 testable. We cover 98,8% of them with 1500 tests. Good luck to all future Bean Validation 1.1 implementors :)

Everything is already available for you to use:

Enjoy!

PS: If you want regular info on Bean Validation, you should go to the Bean Validation website and enlist to the RSS.

It's my pleasure to announce the availability of Bean Validation TCK 1.1.0.CR1 and Hibernate Validator 5.0.0.CR1.

You can find the TCK

  • as Maven artifact in the JBoss Maven repository under the coordinates org.hibernate.beanvalidation.tck:beanvalidation-tck-tests:1.1.0.CR1 and
  • as distribution bundle (ZIP or TAR) on SourceForge

Hibernate Validator can be retrieved

These releases catch up with the proposed final draft of the Bean Validation 1.1 specification, which was handed over to the JCP just yesterday. Check out the announcement for an overview of what has changed feature-wise since the last Beta releases. We addressed 4 issues in the TCK and 16 issues in Hibernate Validator.

As there shall be no blog post without at least a little bit of source code, let's have a closer look at one of the new features, the XML-based configuration of method constraints, implemented with HV-373.

Let's assume there is a class OrderService like this:

public class OrderService {
    public Order placeOrder(String customerId, Item item, int quantity) {
        [...]
    }
}

The following shows an XML constraint mapping for adding method constraints to this class:

<?xml version="1.0" encoding="UTF-8"?>
<constraint-mappings
    xmlns="http://jboss.org/xml/ns/javax/validation/mapping"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping validation-mapping-1.1.xsd"
    version="1.1">
    
    <default-package>com.acme.app.domain</default-package>

    <bean class="OrderService" ignore-annotations="false">
        <method name="placeOrder" ignore-annotations="true">
            <parameter type="java.lang.String">
                <constraint annotation="javax.validation.constraints.NotNull"/>
                <constraint annotation="javax.validation.constraints.Size">
                    <element name="value">5</element>
                </constraint>
            </parameter>
            <parameter type="Item">
                <valid/>
                <constraint annotation="javax.validation.constraints.NotNull"/>
            </parameter>
            <parameter type="int">
                <constraint annotation="javax.validation.constraints.Min">
                    <element name="value">1</element>
                </constraint>
            </parameter>
            <return-value>
                <valid/>
            </return-value>
        </method>
    </bean>
</constraint-mappings>

The following constraints are added here to the placeOrder() method:

  • The customerId parameter must not be null and must be at least five characters long
  • The item parameter must not be null and it is marked for cascaded validation (equivalent to annotating it with @Valid)
  • The quantity parameter must at least be 1
  • The method return value is marked for cascaded validation

What's next?

The final release of Bean Validation 1.1 is coming soon; in the mean time we'll work on more tests for the TCK, fix bugs as required in Hibernate Validator and polish the documentation.

You want to help? Nothing easier than that, just check out the proposed final draft of the specification and play around with all the new features using Hibernate Validator.

You found a bug? You think the implementation doesn't correctly obey to the specification? That's great! We look forward to your report in our issue tracker. You can also reach us via e-mail or in the commmunity forum.

Hibernate Validator 5.0.0.Alpha2 and 4.3.1.Final

Posted by    |       |    Tagged as Hibernate Validator

Today it's my pleasure to announce the simultaneous release of Hibernate Validator 5.0.0.Alpha2 and 4.3.1.Final.

Hibernate Validator 5

The 5.0.0.Alpha2 release catches up with the public review draft of Bean Validation 1.1 (1.1.0.Beta2). Let's have a closer look at some of the changes in the following.

Method validation

The methods for validating method arguments and return values have been moved from javax.validation.Validator to a new dedicated interface MethodValidator. It is obtained and used like this:

MethodValidator methodValidator = Validation
    .buildDefaultValidatorFactory()
    .getValidator()
    .forMethods();

OrderService myOrderService = ...;
Method placeOrderMethod = ...;
Object[] arguments = ...;

Set<ConstraintViolation<OrderService>> = methodValidator
    .validateParameters(myOrderService, placeOrderMethod, arguments);

Also related to method validation, there is now support for cross-parameter constraints. These come in handy when several parameters of a method or constructor need to be validated together, similar to traditional class-level constraints. The following shows an example:

@ConsistentDateParameters
public void createCalendarEvent(Date start, Date end) {
    //...
}

Opposed to constraints on individual parameters, cross-parameter constraints are specified on the method itself. To make it easy for readers of your code to differentiate cross-parameter constraints from return value constraints, it's recommended to choose a name which clearly expresses the constraint's purpose.

A cross-parameter constraint is defined like this:

@Target({ METHOD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@CrossParameterConstraint(validatedBy = ConsistentDateParametersValidator.class)
@Documented
public @interface ConsistentDateParameters {
    String message() default "{ConsistentDateParameters.message}";
    Class<?>[] groups() default { };
    Class<? extends Payload>[] payload() default { };
}

As you can see, this looks very similar to a normal Bean Validation constraint annotation. The only difference is that the @CrossParameterConstraint meta-annotation is used to specify the constraint's validator. The validator must support Object[] as validated type:

public class ConsistentDateParametersValidator implements ConstraintValidator<ConsistentDateParameters, Object[]> {

    @Override
    public void initialize(ConsistentDateParameters constraintAnnotation) {
        //nothing to do
    }

    @Override
    public boolean isValid(Object[] value, ConstraintValidatorContext context) {
        if ( value.length != 2 ) {
            throw new IllegalArgumentException( "Unexpected method signature" );
        }

        if ( value[0] == null || value[1] == null ) {
            return true;
        }

        if ( !( value[0] instanceof Date ) || !( value[1] instanceof Date ) ) {
            throw new IllegalArgumentException( "Unexpected method signature" );
        }

        return ( ( Date ) value[0] ).before( ( Date ) value[1] );
    }
}

As this validator operates on an array of objects representing the method arguments to be validated, it is required to check the number and types of arguments first. The advantage of this approach is that it allows to implement generic cross-parameter constraints which are not specific to one method:

@AreEqual(indexes={0,1}, message="Passwords must be identical")
public void resetPassword(String password, String confirmedPassword) {
    //...
}

The Bean Validation EG also considers a more type-safe approach, which has its own quirks, though. Let us know what would work best for you.

Integration with CDI

One of the big themes in Bean Validation 1.1 is the integration with CDI. The 5.0.0.Alpha2 release brings initial support for this. So it's possible now to have dependencies injected into constraint validator implementations via CDI:

public class OrderNumberValidator implements ConstraintValidator<ValidOrderNumber, String> {

    @Inject
    private OrderValidationService orderValidationService;

    @Override
    public void initialize(ValidOrderNumber constraintAnnotation) {
        //nothing to do
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        return orderValidationService.isValid(value);
    }
}

But that's not all. When invoking a method on a CDI managed bean which has parameter or return value constraints, automatically an interceptor kicks in, which validates the arguments and return value. If either is invalid, a ConstraintViolationException will be thrown. This protects the method implementation from illegal argument values and the caller from illegal return values. So you'll never have to write code like this again:

public void placeOrder(Item item, int quantity) {
    if(item == null) {
        throw new IllegalArgumentException("Item must not be null");
    }
    if(quantity < 1) {
        throw new IllegalArgumentException("Quantity must be at least 1");
    }
    
    //actual implementation
}

Instead this is sufficient:

public void placeOrder(@NotNull Item item, @Min(1) int quantity) {    
    //actual implementation
}

This does not only simplify the implementation, it also makes sure that the caller knows about the constraints, because they are part of the method's public API.

Group conversion

Finally, there is support for the conversion of the validated groups during cascaded validation, a long standing feature request with the Bean Validation spec. Remember, when annotating an element (e.g. a property or method parameter) with @Valid, validation will be propagated to the referenced object(s).

With help of the new ConvertGroup annotation it is now possible to define which group or sequence on the cascaded element shall be validated when a given group is validated on the parent. Let's look at an example:

//validation groups
public interface Complete extends Default {}
public interface BasicPostal {}
public interface FullPostal extends BasicPostal {}

public class Address {
    
    @NotNull(groups = BasicPostal.class)
    String street1;

    @NotNull
    String street2;

    @Size(groups = BasicPostal.class, min = 3)
    String zipCode = "12";

    @Size(groups = FullPostal.class, max = 2)
    String doorCode = "ABC";
}
    
public class User {

    @Valid
    @ConvertGroup.List({
        @ConvertGroup(from = Default.class, to = BasicPostal.class),
        @ConvertGroup(from = Complete.class, to = FullPostal.class)
    })
    Set<Address> addresses = new HashSet<>();
}

When validating a User object with the default group, for the associated addresses the constraints in the BasicPostal group will be validated. When validating a User object with the Complete group, this will lead to a validation of the constraints in the FullPostal group on the user's addresses.

This feature should help with cascaded validations throughout different layers of an application which all define different validation groups.

While these are the major changes of the release, there are some more notable ones, e.g. minor modifications to the metadata API, some changes around ConfigurationSource as well as several bugfixes. Not related to Bean Validation 1.1, we finished the works to clearly separate API, SPI and internal parts of the code base. The changelog has all the details for you.

Hibernate Validator 4.3

While we're heavily working on Hibernate Validator 5 in order to implement revision 1.1 of the Bean Validation spec, we decided to do a maintenance release of Hibernate Validator 4.3, the reference implementation of Bean Validation 1.0.

We fixed a couple of bugs, most notably HV-591. This caused an error when applying the @Email constraint to long strings. Interestingly, this is by far the most reported bug we've had so far in Hibernate Validator with altogether four duplicates. I'm wondering who choses an email address with over 60 characters, but we can validate it now :) Check out the change log for a complete overview of all issues fixed in 4.3.1.

Summing it up

This concludes our tour through the new Hibernate Validator releases.

As usual, both releases can be retrieved from SourceForge (4.3.1.Final, 5.0.0.Alpha2). The Maven coordinates are org.hibernate:hibernate-validator:4.3.1.Final respectively org.hibernate:hibernate-validator:5.0.0.Alpha2. Your feedback is welcome in the forum, the issue tracker and our mailing list. The new features are not described in the Hibernate Validator reference guide yet, so you might be interested in the latest specification draft.

If you have any ideas or proposals around the Bean Validation 1.1 spec, don't hesitate to engage directly with the expert group.

back to top