JSR 303 - Hibernate Validation 4.2.0 - UnexpectedTypeException - @Valid和@Size的组合

时间:2011-11-03 17:03:24

标签: java validation bean-validation

我使用Hibernate Validator(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

}

我从验证器类中删除了泛型表达式:

public class CheckCaseValidator implements ConstraintValidator<CustomConstraint, B> {

... //validation stuff here

}

一切正常。

希望其他人觉得这很有帮助。 最好的祝福, 沃尔特

1 个答案:

答案 0 :(得分:1)

javax.validation.ConstraintValidator<A, T>的javadoc(http://jcp.org/en/jsr/detail?id=303)说:

  

定义为给定对象类型T验证给定约束A的逻辑。实现必须符合以下限制:

     
      
  • T必须解析为非参数化类型
  •   
  • 或T的通用参数必须是无界通配符类型
  •   
  1. (T必须解析为非参数化类型)

    这就是ConstraintValidator<CustomConstraint, B>工作的原因

  2. (或T的通用参数必须是无界通配符类型)

    似乎不起作用,因为ConstraintValidator<CustomConstraint, B<?>>不起作用

  3. 我还找到了different version的javadoc,其中省略了第二个限制。所以可能是官方的javadoc是错的。如果你很好奇,file a bug report for Hibernate Validator(这是参考实现)。如果你不这样做 - 我会; - )