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.