error: No validator could be found for type: java.time.LocalDate

error: No validator could be found for type: java.time.LocalDate

我正在开发一个使用 bean 验证的项目 (Hibernate Validator 5.1.3.Final)。我的 bean 有一个带有 @Past 注释的属性。

@Past(message = "A data deve estar no passado.")
private LocalDate dataAbertura;

但是,当验证发生时,我得到以下异常:

21:46:12,424 ERROR [io.undertow.request] (default task-35) UT005023: Exception handling request to /financeiro/clientes/pessoafisica: javax.servlet.ServletException: javax.validation.UnexpectedTypeException: HV000030: No validator could be found for type: java.time.LocalDate.
    at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:127) [vraptor-4.1.4.jar:]
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:132) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:85) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:61) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:56) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:45) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:63) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:70) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
    at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:261) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:247) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.access[=11=]0(ServletInitialHandler.java:76) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.handleRequest(ServletInitialHandler.java:166) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:197) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.server.HttpServerExchange.run(HttpServerExchange.java:759) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [rt.jar:1.8.0_25]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [rt.jar:1.8.0_25]
    at java.lang.Thread.run(Thread.java:745) [rt.jar:1.8.0_25]
Caused by: javax.validation.UnexpectedTypeException: HV000030: No validator could be found for type: java.time.LocalDate.
    at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager.verifyResolveWasUnique(ConstraintValidatorManager.java:218) [hibernate-validator-5.1.3.Final.jar:5.1.3.Final]
    at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager.findMatchingValidatorClass(ConstraintValidatorManager.java:193) [hibernate-validator-5.1.3.Final.jar:5.1.3.Final]
    at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager.getInitializedValidator(ConstraintValidatorManager.java:97) [hibernate-validator-5.1.3.Final.jar:5.1.3.Final]
    at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:125) [hibernate-validator-5.1.3.Final.jar:5.1.3.Final]

怎么了? Hibernate Validator 不支持 LocalDate?

由于 LocalDate 仍然很新,所以很多库还没有处理它。在我正在处理的项目中,我必须为 LocalDate 编写自定义用户类型。

看看这个休眠问题HHH-8844

他们似乎添加了一个新模块 hibernate-java8 来支持 java 8 的新日期 API。

我知道上面的信息是关于类型映射的,但同样适用于验证。

如果没有开箱即用的解决方案,您可能只需要编写自己的解决方案。请参阅以下页面以获取添加 joda 时间验证器的示例,java 8 个日期应该相似 link

其实要参考的问题是HV-874。 Hibernate Validator 5.2.x 确实添加了对某些新 Java 8 date/time 类型的支持。在这种情况下,我应该强调 "some"。特别是 LocalDate 不受支持。 LocalDate 的 Java 文档说:

This class does not store or represent a time or time-zone. Instead, it is a description of the date, as used for birthdays. It cannot represent an instant on the time-line without additional information such as an offset or time-zone.

如果没有时间轴上的瞬间,则无法判断给定日期是现在还是未来。首先,通过附加时区,可以陈述和回答这个问题。

如果您仍然认为在您的用例中对 LocalDate 使用 Past@Future 约束有意义,您始终可以为 LocalDate 并使用约束映射文件中的 constraint-definition 元素通过 XML 注册它,如 here.

所示

如果您使用的是 Hibernate Validator 5.2,您还可以使用 Java ServiceLoader 方法来注册其他 ConstraintValidator 实现 - 请参阅 ConstraintDefinitionContributor。后者目前是 Hibernate Validator 特定的功能。

javax.validation.constraints(validation-api-2.0.1.Final)中有一个@Past注解

它对 java.time.LocalDate

非常有效