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.