Cross field validation with Hibernate Validator (JSR 303) -
is there implementation of (or third-party implementation for) cross field validation in hibernate validator 4.x? if not, cleanest way implement cross field validator?
as example, how can use api validate 2 bean properties equal (such validating password field matches password verify field).
in annotations, i'd expect like:
public class mybean { @size(min=6, max=50) private string pass; @equals(property="pass") private string passverify; }
each field constraint should handled distinct validator annotation, or in other words it's not suggested practice have 1 field's validation annotation checking against other fields; cross-field validation should done @ class level. additionally, jsr-303 section 2.2 preferred way express multiple validations of same type via list of annotations. allows error message specified per match.
for example, validating common form:
@fieldmatch.list({ @fieldmatch(first = "password", second = "confirmpassword", message = "the password fields must match"), @fieldmatch(first = "email", second = "confirmemail", message = "the email fields must match") }) public class userregistrationform { @notnull @size(min=8, max=25) private string password; @notnull @size(min=8, max=25) private string confirmpassword; @notnull @email private string email; @notnull @email private string confirmemail; }
the annotation:
package constraints; import constraints.impl.fieldmatchvalidator; import javax.validation.constraint; import javax.validation.payload; import java.lang.annotation.documented; import static java.lang.annotation.elementtype.annotation_type; import static java.lang.annotation.elementtype.type; import java.lang.annotation.retention; import static java.lang.annotation.retentionpolicy.runtime; import java.lang.annotation.target; /** * validation annotation validate 2 fields have same value. * array of fields , matching confirmation fields can supplied. * * example, compare 1 pair of fields: * @fieldmatch(first = "password", second = "confirmpassword", message = "the password fields must match") * * example, compare more 1 pair of fields: * @fieldmatch.list({ * @fieldmatch(first = "password", second = "confirmpassword", message = "the password fields must match"), * @fieldmatch(first = "email", second = "confirmemail", message = "the email fields must match")}) */ @target({type, annotation_type}) @retention(runtime) @constraint(validatedby = fieldmatchvalidator.class) @documented public @interface fieldmatch { string message() default "{constraints.fieldmatch}"; class<?>[] groups() default {}; class<? extends payload>[] payload() default {}; /** * @return first field */ string first(); /** * @return second field */ string second(); /** * defines several <code>@fieldmatch</code> annotations on same element * * @see fieldmatch */ @target({type, annotation_type}) @retention(runtime) @documented @interface list { fieldmatch[] value(); } }
the validator:
package constraints.impl; import constraints.fieldmatch; import org.apache.commons.beanutils.beanutils; import javax.validation.constraintvalidator; import javax.validation.constraintvalidatorcontext; public class fieldmatchvalidator implements constraintvalidator<fieldmatch, object> { private string firstfieldname; private string secondfieldname; @override public void initialize(final fieldmatch constraintannotation) { firstfieldname = constraintannotation.first(); secondfieldname = constraintannotation.second(); } @override public boolean isvalid(final object value, final constraintvalidatorcontext context) { try { final object firstobj = beanutils.getproperty(value, firstfieldname); final object secondobj = beanutils.getproperty(value, secondfieldname); return firstobj == null && secondobj == null || firstobj != null && firstobj.equals(secondobj); } catch (final exception ignore) { // ignore } return true; } }
Comments
Post a Comment