Search code examples
bean-validationhibernate-validator

Java bean validation: Enforce a @Pattern only when the property is not blank


I have a form that allows the user to optionally enter their zip code. I know how to validate the format of the zip code, by using a @Pattern constraint and regex. But as this is an optional field, I do not want the format validated if it is blank.

How can I tell the system to ignore the @Pattern constraint if the field is blank? This is an optional field and I only want to validate it if it is not blank.

public class MyForm {
    String firstName;
    String lastName;

    @Pattern(regex = "^\d{5}(?:[-\s]\d{4})?$")
    String optionalZipCode;      // <- This is an optional field.
}

Solution

  • Hardy's solution does work, but I wanted the declaration to be clearer as regular expressions can take a while to decypher. So I ended up creating my own validator @BlankOrPattern based on @Pattern.

    The annotation: BlankOrPattern.java

    @Target( {ElementType.FIELD})
    @Retention(RUNTIME)
    @Documented
    @Constraint(validatedBy = BlankOrPatternValidator.class)
    public @interface BlankOrPattern {
        String regexp();
        Flag[] flags() default {};
        String message() default "{javax.validation.constraints.Pattern.message}";
        Class<?>[] groups() default { };
        Class<? extends Payload>[] payload() default {};
    }
    

    The validator: BlankOrPatternValidator.java

    public class BlankOrPatternValidator implements ConstraintValidator<BlankOrPattern, String> {
    
        private Pattern pattern;
    
        public void initialize(BlankOrPattern parameters) {
            Flag flags[] = parameters.flags();
            int intFlag = 0;
            for (Flag flag : flags) {
                intFlag = intFlag | flag.getValue();
            }
    
            try {
                pattern = compile(parameters.regexp(), intFlag);
            } catch (PatternSyntaxException e) {
                throw new IllegalArgumentException("Invalid regular expression.", e);
            }
        }
    
        public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
            if (value == null || value.length() == 0) {
                return true;
            }
            Matcher m = pattern.matcher(value);
            return m.matches();
        }
    }