HV00030orghibernateconstraintLength异常

bug异常主要信息如下:javax.validation.UnexpectedTypeException: HV00030: No validator could be found for constraint 'org.hibernate.constraint.Length' validating type 'java.time.LocalDateTime' . Check configuration for 'inTime' 如图所示:1.先说明一下该bug的由来,一个微服务A去调用另一个微服务B,微服务B出现了上面的异常日志,而微服务A的异常日志如下,feign.FeignException:status 500 reading xxxhandlexx(String,xxDTO):2.由于被调用的B微服务已经有了异常日志,说明该调用已经发送到B微服务了,我们可以从B微服务的异常日志来排查异常。3.回到第一张图的异常日志,这里已经很清晰了,javax.validation.UnexpectedTypeException: HV00030: No validator could be found for constraint 'org.hibernate.constraint.Length' validating type 'java.time.LocalDateTime' . Check configuration for 'inTime',validation参数校验的时候出现了异常,LocalDateTime类型的变量inTime无法找到有Length的校验约束,请检查'inTime'变量的配置,这里的inTime是方法参数DTO对象的一个字段,如图所示:这里的@Length(max = 30)是导致异常的主要原因,笔者起初inTime的变量类型是String类型,上面加了@Length(max = 30)参数校验,后来换成了LocalDateTime,但是当时也不知道不能用@Length(max = 30)参数校验也忘记去掉了,这里导致方法入参的时候校验失败,抛出异常。那么为什么@Length注解无法用到LocalDateTime变量类型上呢?我们点进去看一下源码:注释:Validate that the string is between min and max included.可以看到只是能用于注解到String类型的变量。把@Length去掉bug就解决了。 如果文章有误,希望指出来。

August 20, 2019 · 1 min · jiezi

Java Bean Validation

案例概述在这本文中,我们将介绍使用标准框架验证Java bean的基础知识 - JSR 380,也称为Bean Validation 2.0。当然,验证用户输入在大多数应用程序中是一个超常见的要求,Java Bean Validation框架已经成为处理这种逻辑的事实上的标准。JSR 380JSR 380是用于bean验证的Java API的规范,是JavaEE和JavaSE的一部分,它使用@NotNull、@Min和@Max等注释确保bean的属性满足特定的标准。此版本需要Java 8或更高版本,并利用Java 8中添加的新功能(如类型注释),并支持Optional和LocalDate等新类型。有关规范的完整信息,请继续阅读JSR 380。依赖性我们将使用Maven示例来显示所需的依赖项,但当然,可以使用各种方式添加这些jar。验证API根据JSR 380规范,validation-api依赖包含标准验证API:<dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.0.Final</version></dependency>验证API参考实现Hibernate Validator是验证API的参考实现。要使用它,我们必须添加以下依赖项:<dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.2.Final</version></dependency><dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator-annotation-processor</artifactId> <version>6.0.2.Final</version></dependency>这里快速说明的是,hibernate-validator完全独立于Hibernate的持久性方面,并且通过将其添加为依赖项,我们不会将这些持久性方面添加到项目中。表达式语言依赖关系JSR 380提供对变量插值的支持,允许在违规消息中使用表达式。要解析这些表达式,我们必须在表达式语言API和该API的实现上添加依赖项。GlassFish提供参考实现:<dependency> <groupId>javax.el</groupId> <artifactId>javax.el-api</artifactId> <version>3.0.0</version></dependency> <dependency> <groupId>org.glassfish.web</groupId> <artifactId>javax.el</artifactId> <version>2.2.6</version></dependency>如果未添加这些JAR,您将在运行时收到错误消息,如下所示:HV000183:无法加载’javax.el.ExpressionFactory’。检查您是否在类路径上有EL依赖项,或使用ParameterMessageInterpolator使用验证注释我们将在这里使用User bean作为主要示例,并为其添加一些简单的验证:import javax.validation.constraints.AssertTrue;import javax.validation.constraints.Max;import javax.validation.constraints.Min;import javax.validation.constraints.NotNull;import javax.validation.constraints.Size;import javax.validation.constraints.Email; public class User { @NotNull(message = “Name cannot be null”) private String name; @AssertTrue private boolean working; @Size(min = 10, max = 200, message = “About Me must be between 10 and 200 characters”) private String aboutMe; @Min(value = 18, message = “Age should not be less than 18”) @Max(value = 150, message = “Age should not be greater than 150”) private int age; @Email(message = “Email should be valid”) private String email; // standard setters and getters }示例中使用的所有注释都是标准的JSR注释:@NotNull - 验证带注释的属性值不为 null@AssertTrue - 验证带注释的属性值是否为 true@Size - 验证带注释的属性值是否具有属性min和max之间的大小; 可以应用于String, Collection, Map和数组属性@Min - 验证带注释的属性的值是否小于value属性@Max - 验证带注释的属性的值是否大于value属性@Email - 验证带注释的属性是否为有效的电子邮件地址某些注释接受其他属性,但message属性对所有属性都是通用的。这是当相应属性的值未通过验证时通常会呈现的消息。可以在JSR中找到的一些其他注释是:@NotEmpty - 验证属性不为null或为空; 可以应用于String, Collection, Map或 Array值@NotBlank - 只能应用于文本值,并验证该属性不是null或空格@Positive和@PositiveOrZero - 适用于数值并验证它们是严格正数还是正数,包括0@Negative和@NegativeOrZero - 适用于数值并验证它们是严格为负数,还是负数,包括0@Past和@PastOrPresent - 验证日期值是否过去,包括现在; 可以应用于日期类型,包括Java 8中添加的日期类型@Future和@FutureOrPresent - 验证日期值是否将来包括现在验证注释也可以应用于集合的元素:List<@NotBlank String> preferences;在这种情况下,将验证添加到选项列表中的任何值。该规范还支持 Java 8中的新Optional类型:private LocalDate dateOfBirth; public Optional<@Past LocalDate> getDateOfBirth() { return Optional.of(dateOfBirth);}在这里,验证框架将自动解包LocalDate值并对其进行验证。程序验证一些框架 - 例如Spring–只需使用注释就可以通过简单的方法触发验证过程。这主要是为了使我们不必与程序验证API进行交互。现在让我们进入手动路线并以编程方式设置:ValidatorFactory factory = Validation.buildDefaultValidatorFactory();Validator validator = factory.getValidator();要验证bean,我们必须首先拥有Validator对象,该对象使用ValidatorFactory构造。定义Bean我们现在要设置一个无效用户 - 使用空名称值:User user = new User();user.setWorking(true);user.setAboutMe(“Its all about me!”);user.setAge(50);验证Bean现在我们有了一个Validator,我们可以通过将它传递给validate方法来验证我们的bean 。任何违反User对象中定义的约束的行为都将作为Set返回。Set<ConstraintViolation<User>> violations = validator.validate(user);通过迭代违规,我们可以使用getMessage方法获取所有违规消息。for (ConstraintViolation<User> violation : violations) { log.error(violation.getMessage()); }在我们的示例中(ifNameIsNull_nameValidationFails),该集合将包含一个ConstraintViolation,消息“ Name not not null”。案例结论本文重点介绍了标准Java Validation API的简单传递,并使用javax.validation注释和API 说明了bean验证的基础知识。 ...

January 23, 2019 · 1 min · jiezi