specified org method for failed annotationexception hibernate validation spring-mvc hibernate-validator

for - invocation of init method failed nested exception is org hibernate annotationexception



Validador de Hibernate: @Email acepta ask @ stackoverflow como válido? (7)

Estoy usando la anotación @Email para validar una dirección de correo electrónico. El problema que estoy teniendo es que está aceptando cosas como ask@stackoverflow como una dirección válida de correo electrónico. Supongo que esto se debe a que quieren admitir direcciones de intranet, pero parece que no puedo encontrar una bandera, así que compruebo si hay una extensión.

¿Realmente necesito cambiar a @Pattern (y cualquier recomendación para un patrón de correo electrónico que sea flexible) o me falta algo?


Aquí hay un validador de correo electrónico javax.validation que utiliza el validador de Apache Commons

public class CommonsEmailValidator implements ConstraintValidator<Email, String> { private static final boolean ALLOW_LOCAL = false; private EmailValidator realValidator = EmailValidator.getInstance(ALLOW_LOCAL); @Override public void initialize(Email email) { } @Override public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) { if( s == null ) return true; return realValidator.isValid(s); } }

Y la anotación:

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = {CommonsEmailValidator.class}) @Documented @ReportAsSingleViolation public @interface Email { String message() default "{org.hibernate.validator.constraints.Email.message}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface List { Email[] value(); } }


De hecho, @Email de Hibernate Validator usa la @Email internamente . Puede definir fácilmente su propia restricción en función de esa expresión regular, modificada como necesite (tenga en cuenta el + al final de DOMAIN ):

@Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = {}) @Pattern(regexp = Constants.PATTERN, flags = Pattern.Flag.CASE_INSENSITIVE) public @interface EmailWithTld { String message() default "Wrong email"; Class<?>[] groups() default { }; Class<? extends Payload>[] payload() default { }; } interface Constants { static final String ATOM = "[a-z0-9!#$%&''*+/=?^_`{|}~-]"; static final String DOMAIN = "(" + ATOM + "+(//." + ATOM + "+)+"; static final String IP_DOMAIN = "//[[0-9]{1,3}//.[0-9]{1,3}//.[0-9]{1,3}//.[0-9]{1,3}//]"; static final String PATTERN = "^" + ATOM + "+(//." + ATOM + "+)*@" + DOMAIN + "|" + IP_DOMAIN + ")$"; }


En realidad, validar las direcciones de correo electrónico es realmente complejo. No es posible validar que una dirección de correo electrónico sea sintácticamente correcta y se dirija al destinatario en una anotación. La anotación @Email es una comprobación mínima útil que no sufre el problema de falsos negativos.

El siguiente paso en la validación debería ser enviar un correo electrónico con un desafío que el usuario debe completar para establecer que el usuario tiene acceso a la dirección de correo electrónico.

Es mejor aceptar algunos falsos positivos en el paso 1 y permitir el paso de algunas direcciones de correo electrónico no válidas que rechazar usuarios válidos. Si desea aplicar reglas adicionales, puede agregar más controles, pero tenga mucho cuidado con lo que supone que es un requisito de una dirección de correo electrónico válida. Por ejemplo, no hay nada en los RFC que dicte que i@nl sea ​​inválido, porque nl es un dominio de nivel superior de un país registrado.


La solución de composición de restricción no funciona. Cuando el correo electrónico se utiliza junto con el patrón, la expresión regular de correo electrónico se mantiene en mayor precedencia. Creo que esto se debe a que la anotación de Email anula algunos atributos del patrón, a saber, flags y regexp (la clave aquí). Si @Email , solo la expresión regular de @Pattern aplicará en las validaciones.

/** * @return an additional regular expression the annotated string must match. The default is any string (''.*'') */ @OverridesAttribute(constraint = Pattern.class, name = "regexp") String regexp() default ".*"; /** * @return used in combination with {@link #regexp()} in order to specify a regular expression option */ @OverridesAttribute(constraint = Pattern.class, name = "flags") Pattern.Flag[] flags() default { };


Obviamente, llegué tarde a la fiesta, todavía estoy respondiendo a esta pregunta,

¿Por qué no podemos usar la anotación @Pattern con expresiones regulares en nuestra clase de Validación como esta?

public Class Sigunup { @NotNull @NotEmpty @Pattern((regexp="[A-Za-z0-9._%-+]+@[A-Za-z0-9.-]+//.[A-Za-z]{2,4}") private String email; }

Es mas fácil.


Si va a probar la solución anterior, https://.com/a/12515543/258544 agregue @ReportAsSingleViolation en la definación de la anotación, de esta forma evitará ambos mensajes de validación (uno de @Email y otro de @Pattern) ya que es una anotación compuesta:

@Email(message="Please provide a valid email address") @Pattern(regexp=".+@.+//..+", message="Please provide a valid email address") @Target( { METHOD, FIELD, ANNOTATION_TYPE }) @Retention(RUNTIME) @Constraint(validatedBy = {}) @Documented @ReportAsSingleViolation

From @interface ReportAsSingleViolation javax.validation: validation-api: 1.1.0.Final) definición de anotación: "... La evaluación de las restricciones compuestas se detiene en el primer error de validación en caso de que la restricción de composición esté anotada con ReportAsSingleViolation"


También puede usar la composición de restricciones como una solución alternativa. En el siguiente ejemplo, confío en el validador @Email para hacer la validación principal, y agrego un validador @Pattern para asegurarme de que la dirección sea en forma de x@yz (no recomiendo usar solo @Pattern continuación para validación regular de correo electrónico)

@Email(message="Please provide a valid email address") @Pattern(regexp=".+@.+//..+", message="Please provide a valid email address") @Target( { METHOD, FIELD, ANNOTATION_TYPE }) @Retention(RUNTIME) @Constraint(validatedBy = {}) @Documented public @interface ExtendedEmailValidator { String message() default "Please provide a valid email address"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }