Can a custom validator have multiple messages based on what validation failed in hibernate validator?

StackOverflow https://stackoverflow.com/questions/22102175

I have a custom validation to check an email field in a class.

annotation interface:

@ReportAsSingleViolation
@NotBlank
@Email
@Target({ CONSTRUCTOR, FIELD, METHOD, PARAMETER, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = CustomEmailValidator.class)
@Documented
public @interface CustomEmail {
  String message() default "Failed email validation.";

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

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

CustomEmailValidator class:

public class CustomEmailValidator implements ConstraintValidator<CustomEmail, String> {

  public void initialize(CustomEmail customEmail) {
    // nothing to initialize
  }

  public boolean isValid(String email, ConstraintValidatorContext arg1) {
    if (email != null) {
    String domain = "example.com";
    String[] emailParts = email.split("@");

      return (emailParts.length == 2 && emailParts[1].equals(domain));
    } else {
      return false;
    }
  }
}  

I use a ValidationMessages.properties file for all of my custom messages. in the properties file I reference a failure in the above code using:

CustomEmail.email=The provided email can not be added to the account.  

The problem is that this error message is used for all failures during validation, so even if the user provided a blank string it will print that message. What I want to do is if the validation fails on @NotBlank then print a "required field message", if it fails on @Email provide a "invalid email" message. Then only for when it fails the custom validation would it print the CustomEmail.email message. Also in my annotation interface do the @NotBlank and @Email occur in order or are they randomly run. Then what ever validation is run first is returned as the error? My validation requires that they run in the order they are listed @NotBlank followed by @Email followed by CustomEmail.

有帮助吗?

解决方案

Note that in your custom constraints there is no order defined. Even so you first list @NotBlank and then @Email, there is no order guarantee. Java itself does not define any order in annotations. If you want to define an order you need to use groups and/or group sequence. In this case you also cannot use a composed constraints, since group definition on the composing constraints are ignored. Only the group of the main constraint applies.

其他提示

You could create an Enum defining the types of expected errors, and then use its value to retrieve the proper error message from your configuration. Something like

/**
  <P>Defines the type of email-formatting error message.</P>
 **/
public enum EmailErrorTypeIs {
  /**
     <P>...</P>

     @see  #INVALID
     @see  #OTHER
   **/
  BLANK,
  /**
     <P>...</P>

     @see  #BLANK
   **/
  INVALID,
  /**
     <P>...</P>

     @see  #BLANK
   **/
  OTHER;
};

Which you would use like this:

if(input == null  ||  input.length() == 0)  {
   throw  new IllegalArgumentException(getErrorFromConfig(EmailErrorTypeIs.BLANK));
}  else  if...

Turn off @ReportAsSingleViolation. You'll get a ConstraintViolation for each violation, and can work accordingly.

As for order, following @Hardy's answer.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top