Gamblit
Gamblit

Reputation: 31

JSR 303 custom constraint message

On a Spring MVC application I've developed a custom JSR 303 constraint as follows:

@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {})
@Pattern(regexp = EmailWithTld.PATTERN, flags = Pattern.Flag.CASE_INSENSITIVE)
public @interface EmailWithTld {

    static final String PATTERN = "(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])";

    String message() default "{springtest.constraints.EmailWithTld.message}";

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

    Class<? extends Payload>[] payload() default {};

}

The problem is that the message value is ignored, and the message that is displayed on validation error is the one from @Pattern ("must match "(?:[a-z0-9!#$%&.....")

I was expecting it to return my message, from the message variable.

One way i can get a custom message is by replacing the above @Pattern with

@Pattern(message="{springtest.constraints.EmailWithTld.message}", regexp = EmailWithTld.PATTERN, flags = Pattern.Flag.CASE_INSENSITIVE)

If I do it this way the correct message does show up, provided I use the resource bundle for setting it. If set via the annotation usage, it does not work. Example:

@Pattern(message="Testing 1 2 3}"

What is the correct way to do it?

Upvotes: 2

Views: 1618

Answers (1)

Gamblit
Gamblit

Reputation: 31

After spending a whole 3 hours, I've found the answer by looking at the Hibernate Validator source and it was actually quite simple...

Add a @ReportAsSingleViolation annotation to the class.

This works:

@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {})
@ReportAsSingleViolation
@Pattern(regexp = EmailWithTld.PATTERN, flags = Pattern.Flag.CASE_INSENSITIVE)
public @interface EmailWithTld {

    static final String PATTERN = "(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])";

    String message() default "{springtest.constraints.EmailWithTld.message}";

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

    Class<? extends Payload>[] payload() default {};

}

Upvotes: 1

Related Questions