UnsupportedOperationException when using @Past constraint

Hello,

I run into a problem.

I have persistent field of type java.util.Date with the following annotations

	@NotNull
	@Temporal(TemporalType.DATE)
	@Past
	private Date birthDate;

In a container managed transaction I run the following test to reproduce my problem :

		List<Entity> entities = entityManager.findAll();
		for (Entity entity : entities) {
 			em.detach(diver);
			entity.setAnotherPropertieThanBirthDate("+33555123456");
			diverManager.persist(diver);
		}		

This lead to the following exception :

Caused by: javax.validation.ValidationException: HV000028: Unexpected exception during isValid call.
	at org.hibernate.validator@6.0.22.Final//org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateSingleConstraint(ConstraintTree.java:177)
	at org.hibernate.validator@6.0.22.Final//org.hibernate.validator.internal.engine.constraintvalidation.SimpleConstraintTree.validateConstraints(SimpleConstraintTree.java:68)
	at org.hibernate.validator@6.0.22.Final//org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:73)
	at org.hibernate.validator@6.0.22.Final//org.hibernate.validator.internal.metadata.core.MetaConstraint.doValidateConstraint(MetaConstraint.java:127)
	at org.hibernate.validator@6.0.22.Final//org.hibernate.validator.internal.metadata.core.MetaConstraint.validateConstraint(MetaConstraint.java:120)
	at org.hibernate.validator@6.0.22.Final//org.hibernate.validator.internal.engine.ValidatorImpl.validateMetaConstraint(ValidatorImpl.java:552)
	at org.hibernate.validator@6.0.22.Final//org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForSingleDefaultGroupElement(ValidatorImpl.java:515)
	at org.hibernate.validator@6.0.22.Final//org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:485)
	at org.hibernate.validator@6.0.22.Final//org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:447)
	at org.hibernate.validator@6.0.22.Final//org.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:397)
	at org.hibernate.validator@6.0.22.Final//org.hibernate.validator.internal.engine.ValidatorImpl.validate(ValidatorImpl.java:173)
	at org.hibernate@5.3.24.Final//org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:116)
	at org.hibernate@5.3.24.Final//org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreUpdate(BeanValidationEventListener.java:88)
	at org.hibernate@5.3.24.Final//org.hibernate.action.internal.EntityUpdateAction.preUpdate(EntityUpdateAction.java:248)
	at org.hibernate@5.3.24.Final//org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:119)
	at org.hibernate@5.3.24.Final//org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604)
	at org.hibernate@5.3.24.Final//org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:478)
	at org.hibernate@5.3.24.Final//org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:356)
	at org.hibernate@5.3.24.Final//org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
	at org.hibernate@5.3.24.Final//org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1472)
	at org.hibernate@5.3.24.Final//org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1458)
	at org.jboss.as.jpa@26.0.0.Beta1//org.jboss.as.jpa.container.AbstractEntityManager.flush(AbstractEntityManager.java:462)
	at deployment.DivingReservationEAR.ear.DivingReservation.jar//com.grecland.DivingReservation.ejb.session.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:43)
	at jdk.internal.reflect.GeneratedMethodAccessor78.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.jboss.as.ee@26.0.0.Beta1//org.jboss.as.ee.component.ManagedReferenceMethodInterceptor.processInvocation(ManagedReferenceMethodInterceptor.java:52)
	at org.jboss.invocation@1.7.0.Final//org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
	at org.jboss.invocation@1.7.0.Final//org.jboss.invocation.InterceptorContext$Invocation.proceed(InterceptorContext.java:509)
	at org.jboss.as.weld.ejb@26.0.0.Beta1//org.jboss.as.weld.ejb.DelegatingInterceptorInvocationContext.proceed(DelegatingInterceptorInvocationContext.java:92)
	at org.jboss.weld.core@3.1.8.Final//org.jboss.weld.interceptor.proxy.WeldInvocationContextImpl.interceptorChainCompleted(WeldInvocationContextImpl.java:107)
	at org.jboss.weld.core@3.1.8.Final//org.jboss.weld.interceptor.proxy.WeldInvocationContextImpl.proceed(WeldInvocationContextImpl.java:126)
	at org.jboss.weld.probe@3.1.8.Final//org.jboss.weld.probe.InvocationMonitor$InterceptorAction.proceed(InvocationMonitor.java:199)
	at org.jboss.weld.probe@3.1.8.Final//org.jboss.weld.probe.InvocationMonitor$InterceptorAction.proceed(InvocationMonitor.java:195)
	at org.jboss.weld.probe@3.1.8.Final//org.jboss.weld.probe.InvocationMonitor$Action.perform(InvocationMonitor.java:174)
	at org.jboss.weld.probe@3.1.8.Final//org.jboss.weld.probe.InvocationMonitor.monitor(InvocationMonitor.java:139)
	at jdk.internal.reflect.GeneratedMethodAccessor36.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.jboss.weld.core@3.1.8.Final//org.jboss.weld.interceptor.reader.SimpleInterceptorInvocation$SimpleMethodInvocation.invoke(SimpleInterceptorInvocation.java:73)
	at org.jboss.weld.core@3.1.8.Final//org.jboss.weld.interceptor.proxy.WeldInvocationContextImpl.invokeNext(WeldInvocationContextImpl.java:92)
	at org.jboss.weld.core@3.1.8.Final//org.jboss.weld.interceptor.proxy.WeldInvocationContextImpl.proceed(WeldInvocationContextImpl.java:124)
	at org.jboss.weld.core@3.1.8.Final//org.jboss.weld.bean.InterceptorImpl.intercept(InterceptorImpl.java:105)
	at org.jboss.as.weld.ejb@26.0.0.Beta1//org.jboss.as.weld.ejb.DelegatingInterceptorInvocationContext.proceed(DelegatingInterceptorInvocationContext.java:82)
	at org.jboss.as.weld.ejb@26.0.0.Beta1//org.jboss.as.weld.interceptors.EjbComponentInterceptorSupport.delegateInterception(EjbComponentInterceptorSupport.java:60)
	at org.jboss.as.weld.common@26.0.0.Beta1//org.jboss.as.weld.interceptors.Jsr299BindingsInterceptor.delegateInterception(Jsr299BindingsInterceptor.java:77)
	at org.jboss.as.weld.common@26.0.0.Beta1//org.jboss.as.weld.interceptors.Jsr299BindingsInterceptor.doMethodInterception(Jsr299BindingsInterceptor.java:89)
	at org.jboss.as.weld.common@26.0.0.Beta1//org.jboss.as.weld.interceptors.Jsr299BindingsInterceptor.processInvocation(Jsr299BindingsInterceptor.java:102)
	at org.jboss.as.ee@26.0.0.Beta1//org.jboss.as.ee.component.interceptors.UserInterceptorFactory$1.processInvocation(UserInterceptorFactory.java:63)
	at org.jboss.invocation@1.7.0.Final//org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
	at org.jboss.as.ejb3@26.0.0.Beta1//org.jboss.as.ejb3.component.invocationmetrics.ExecutionTimeInterceptor.processInvocation(ExecutionTimeInterceptor.java:43)
	at org.jboss.invocation@1.7.0.Final//org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
	at org.jboss.as.jpa@26.0.0.Beta1//org.jboss.as.jpa.interceptor.SBInvocationInterceptor.processInvocation(SBInvocationInterceptor.java:47)
	at org.jboss.invocation@1.7.0.Final//org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
	at org.jboss.as.ee@26.0.0.Beta1//org.jboss.as.ee.concurrent.ConcurrentContextInterceptor.processInvocation(ConcurrentContextInterceptor.java:45)
	at org.jboss.invocation@1.7.0.Final//org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
	at org.jboss.invocation@1.7.0.Final//org.jboss.invocation.InitialInterceptor.processInvocation(InitialInterceptor.java:40)
	at org.jboss.invocation@1.7.0.Final//org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
	at org.jboss.invocation@1.7.0.Final//org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:53)
	at org.jboss.as.ee@26.0.0.Beta1//org.jboss.as.ee.component.interceptors.ComponentDispatcherInterceptor.processInvocation(ComponentDispatcherInterceptor.java:52)
	at org.jboss.invocation@1.7.0.Final//org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
	at org.jboss.as.ejb3@26.0.0.Beta1//org.jboss.as.ejb3.component.pool.PooledInstanceInterceptor.processInvocation(PooledInstanceInterceptor.java:51)
	at org.jboss.invocation@1.7.0.Final//org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
	at org.jboss.as.ejb3@26.0.0.Beta1//org.jboss.as.ejb3.component.interceptors.AdditionalSetupInterceptor.processInvocation(AdditionalSetupInterceptor.java:56)
	at org.jboss.invocation@1.7.0.Final//org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
	at org.jboss.as.ejb3@26.0.0.Beta1//org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInOurTx(CMTTxInterceptor.java:254)
	... 128 more
Caused by: java.lang.UnsupportedOperationException
	at java.sql/java.sql.Date.toInstant(Date.java:316)
	at org.hibernate.validator@6.0.22.Final//org.hibernate.validator.internal.constraintvalidators.bv.time.past.PastValidatorForDate.getInstant(PastValidatorForDate.java:23)
	at org.hibernate.validator@6.0.22.Final//org.hibernate.validator.internal.constraintvalidators.bv.time.past.PastValidatorForDate.getInstant(PastValidatorForDate.java:19)
	at org.hibernate.validator@6.0.22.Final//org.hibernate.validator.internal.constraintvalidators.bv.time.AbstractInstantBasedTimeValidator.isValid(AbstractInstantBasedTimeValidator.java:55)
	at org.hibernate.validator@6.0.22.Final//org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateSingleConstraint(ConstraintTree.java:171)
	... 193 more

I understand that the BirthDate’s return value is of type java.sql.Date witch extend java.util.Date.
When this type is validated by the PastValidatorForDate validator, the validator call the toInstant() method, witch throws UnsupportedOperationException when the instance is of type java.sql.Date.

Is my analyse correct? Is there a workaroud? Did i misconfigure something?

Try using java.time.OffsetDateTime or java.time.LocalDate instead of java.sql.Date.
the documentation for Past provide the supported classes, u can look it up if u want to other wise these are the supported classes

 *     <li>{@code java.util.Date}</li>
 *     <li>{@code java.util.Calendar}</li>
 *     <li>{@code java.time.Instant}</li>
 *     <li>{@code java.time.LocalDate}</li>
 *     <li>{@code java.time.LocalDateTime}</li>
 *     <li>{@code java.time.LocalTime}</li>
 *     <li>{@code java.time.MonthDay}</li>
 *     <li>{@code java.time.OffsetDateTime}</li>
 *     <li>{@code java.time.OffsetTime}</li>
 *     <li>{@code java.time.Year}</li>
 *     <li>{@code java.time.YearMonth}</li>
 *     <li>{@code java.time.ZonedDateTime}</li>
 *     <li>{@code java.time.chrono.HijrahDate}</li>
 *     <li>{@code java.time.chrono.JapaneseDate}</li>
 *     <li>{@code java.time.chrono.MinguoDate}</li>
 *     <li>{@code java.time.chrono.ThaiBuddhistDate}</li>

Totally. Use java.util.Date or things from java.time. You shouldn’t use java.sql.Date nowadays.

Hello

Thanks for your the ansers.

I didn’t use java.sql.Date. My field birthDate is defined as a java.util.Date, not as java.sql.Date.
The java.sql.Date seem to be returned by Hibernate while retrieving my persisted Entity and the error come when I try to persist a modified object retrieved from the DB.

To give more detail in the environnement, I’m using WILDLFY 26.0.0-Final with the embedded H2 database.
Wildlfy use hibernate-validator-6.0.22.Final.jar and hibernate-core-5.3.24.Final.jar