JSR 303 — Проверка гибернации 4.2.0 — Неожиданное исключение типа — @Valid и @Size в комбинации

#java #validation #bean-validation

#java #проверка #проверка компонента

Вопрос:

У меня странное поведение при использовании средства проверки гибернации (JSR 303) и аннотирования свойства типа java.util.List

Следующая кодовая база:

 public class A {
  @Valid @NotNull @Size(min=1, max=15)
  private List<B<?>> validList = new ArrayList<B<?>>();
  ...
}
  

Если я начну проверку, я получу следующее исключение:

 javax.validation.UnexpectedTypeException: No validator could be found for type: B
at org.hibernate.validator.engine.ConstraintTree.verifyResolveWasUnique(ConstraintTree.java:383)
at org.hibernate.validator.engine.ConstraintTree.findMatchingValidatorClass(ConstraintTree.java:364)
at org.hibernate.validator.engine.ConstraintTree.getInitializedValidator(ConstraintTree.java:313)
at org.hibernate.validator.engine.ConstraintTree.validateConstraints(ConstraintTree.java:144)
at org.hibernate.validator.engine.ConstraintTree.validateConstraints(ConstraintTree.java:117)
at org.hibernate.validator.metadata.MetaConstraint.validateConstraint(MetaConstraint.java:84)
at org.hibernate.validator.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:452)
at org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:397)
at org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:361)
at org.hibernate.validator.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:313)
at org.hibernate.validator.engine.ValidatorImpl.validateCascadedConstraint(ValidatorImpl.java:613)
at org.hibernate.validator.engine.ValidatorImpl.validateCascadedConstraints(ValidatorImpl.java:478)
at org.hibernate.validator.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:322)
at org.hibernate.validator.engine.ValidatorImpl.validate(ValidatorImpl.java:139)
  

Если я изменю свой код (и, следовательно, к сожалению, свою семантику) следующим образом:

 public class A {
  @Valid @NotNull @Size(min=0, max=15)
  private List<B<?>> validList = new ArrayList<B<?>>();
  ...
}
  

все без исключения проверяется нормально.

Какую часть я пропустил? Есть ли у кого-нибудь идеи, почему это не работает?

Я выяснил, в чем проблема. У меня есть настраиваемое ограничение для класса B

 @CustomConstraint
public class B {
}
  

ограничение:

 @Target( { METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = CustomConstraintValidator.class)
@Documented
public @interface CustomConstraint {

  String message() default "{com.mycompany.constraints.checkcase}";

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

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

}
  

и средство проверки:

 public class CheckCaseValidator implements ConstraintValidator<CustomConstraint, B<? extends C>> {

... //validation stuff here

}
  

после того, как я удалил выражение generics из класса validator:

 public class CheckCaseValidator implements ConstraintValidator<CustomConstraint, B> {

... //validation stuff here

}
  

все работало нормально.

Надеюсь, что другие люди найдут это полезным. С наилучшими пожеланиями, Уолтер

Комментарии:

1. Вы уверены, что это как-то связано с @Size ? Для меня такое же исключение также возникает, когда @Valid присутствует только.

Ответ №1:

javadoc (http://jcp.org/en/jsr/detail?id=303 ) ибо javax.validation.ConstraintValidator<A, T> говорит:

Определяет логику для проверки заданного ограничения A для данного типа объекта T. Реализации должны соответствовать следующему ограничению:

  • T должен разрешаться в непараметризованный тип
  • или общие параметры T должны быть неограниченными подстановочными знаками
  1. (T должен разрешаться в непараметризованный тип)

    вот почему ConstraintValidator<CustomConstraint, B> работает

  2. (или общие параметры T должны быть неограниченными типами подстановочных знаков)

    похоже, не работает, так как ConstraintValidator<CustomConstraint, B<?>> тоже не работает

Я также нашел другую версию javadoc, в которой второе ограничение не указано. Так что может быть, что официальный javadoc просто неверен. Если вам интересно, отправьте отчет об ошибке для Hibernate Validator (это эталонная реализация). Если вы этого не сделаете — я сделаю 😉