Is there an implementation of (or third-party implementation for) cross field validation in Hibernate Validator 4.x? If not, what is the cleanest way to implement a cross field validator?
As an example, how can you use the API to validate two bean properties are equal (such as validating a password field matches the password verify field).
In annotations, I'd expect something like:
public class MyBean {
@Size(min=6, max=50)
private String pass;
@Equals(property="pass")
private String passVerify;
}
Use
@EqualProperties
from this dedicated JSR-303 constraint library:With Hibernate Validator 4.1.0.Final I recommend using @ScriptAssert:
Nothing wrong with a custom class level validator @Matches solution.
I'm surprised this isn't available out of the box. Anyway, here is a possible solution.
I've created a class level validator, not the field level as described in the original question.
Here is the annotation code:
And the validator itself:
Note that I've used MVEL to inspect the properties of the object being validated. This could be replaced with the standard reflection APIs or if it is a specific class you are validating, the accessor methods themselves.
The @Matches annotation can then be used used on a bean as follows:
As a disclaimer, I wrote this in the last 5 minutes, so I probably haven't ironed out all the bugs yet. I'll update the answer if anything goes wrong.
Each field constraint should be handled by a distinct validator annotation, or in other words it's not suggested practice to have one field's validation annotation checking against other fields; cross-field validation should be done at the class level. Additionally, the JSR-303 Section 2.2 preferred way to express multiple validations of the same type is via a list of annotations. This allows the error message to be specified per match.
For example, validating a common form:
The Annotation:
The Validator:
You guys are awesome. Really amazing ideas. I like Alberthoven's and McGin's most, so I decided to combine both ideas. And develop some generic solution to cater all cases. Here is my proposed solution.
Cross fields validations can be done by creating custom constraints.
Example:- Compare password and confirmPassword fields of User instance.
CompareStrings
StringComparisonMode
CompareStringsValidator
ConstraintValidatorHelper
User
Test
Output
Message:- [Password, ConfirmPassword] must be equal.
By using the CompareStrings validation constraint, we can also compare more than two properties and we can mix any of four string comparison methods.
ColorChoice
Test
Output
Message:- Please choose three different colors.
Similarly, we can have CompareNumbers, CompareDates, etc cross-fields validation constraints.
P.S. I have not tested this code under production environment (though I tested it under dev environment), so consider this code as Milestone Release. If you find a bug, please write a nice comment. :)