13

How can i use @Pattern constraint on non-mandatory form fields ?

@Pattern(regexp="...")
private String something;

as soon as i submit my form, i get validation error as expected but the user may leave the field empty, since this is not a mandatory field.

PS: i could write my own constraint annotation. However, i just ask an easier way combining annotations or adding annotation attributes. JSR303 implementation is hibernate-validator.

Erhan Bagdemir
  • 5,231
  • 6
  • 34
  • 40

3 Answers3

7

Just set it with null instead of empty string. Since empty HTML input fields are by default submitted as an empty string as HTTP request parameter, you need to let your MVC framework interpret empty submitted values as null. This is in JSF easy done by a <context-param> in web.xml. However, since you're using Spring MVC and I don't do it, I searched a bit here and found this answer which may be of use.

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • and would it be valid both pattern match and null ? i mean, the both inputs are valid null (in my case an empty) and text matched by regexp. i would except from validator still a validation failure, because the pattern won't be matched, if it comes null. – Erhan Bagdemir May 14 '11 at 00:37
  • 1
    If the value is `null`, then `@Pattern` won't be tested. Only `@NotNull` (and Hibernate-specific `@NotEmpty`) will be tested. – BalusC May 14 '11 at 00:39
  • I did exactly as mentioned above and an empty field was not validated by JSF. When persisting the entity with @Pattern I got ConstraintViolationException from JPA. Is it a difference validating in JSF and JPA? – Dan Feb 08 '13 at 12:34
3

Another way to address this issue is to allow the empty string as alternative valid value in your regular expression (using "|").

As BalusC said in JSF 2 it's possible to convert empty strings automatically to null. The context parameter to use is "javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL", which must be set to "true" (see also this answer).

Community
  • 1
  • 1
Gunnar
  • 18,095
  • 1
  • 53
  • 73
0

Adding a Empty Constraint is the best way to go. In this constraint you add your own @Pattern as the composing constraint.

@Target({ANNOTATION_TYPE, FIELD})
@Retention(RUNTIME)
@Documented
**@Pattern(regexp="...")**
@Constraint(validatedBy = EmptyValueConstraintValidator.class)
public @interface EmptyValueConstraint  {
    String message() default "{defaultMessage}";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
    @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
    @Retention(RUNTIME)
    @Documented
    @interface List {
        EmptyValueConstraint[] value();
    }
}

public class EmptyValueConstraintValidator  implements     
ConstraintValidator<EmptyValueConstraint, Object>{

    @Override
    public void initialize(EmptyValueConstraint constraintAnnotation) {

    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {

        return true;
    }



}

Hope this helps..