From 818dd8da36a80adb2dbc6e77324558a8b8ee176f Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Fri, 19 Sep 2025 23:43:13 +0200 Subject: [PATCH] Update to Hibernate Validator 9.1 --- .../test/CustomConfigurationViaBeansTest.java | 5 +- .../AbstractMethodValidationInterceptor.java | 5 ++ .../runtime/jaxrs/ConstraintTypeUtil20.java | 65 ++++++++++--------- ...teasyReactiveViolationExceptionMapper.java | 6 ++ .../jaxrs/ResteasyViolationExceptionImpl.java | 4 +- pom.xml | 2 +- 6 files changed, 51 insertions(+), 36 deletions(-) diff --git a/extensions/hibernate-validator/deployment/src/test/java/io/quarkus/hibernate/validator/test/CustomConfigurationViaBeansTest.java b/extensions/hibernate-validator/deployment/src/test/java/io/quarkus/hibernate/validator/test/CustomConfigurationViaBeansTest.java index 6a1f079f4aaa7..bb4c19bdf8802 100644 --- a/extensions/hibernate-validator/deployment/src/test/java/io/quarkus/hibernate/validator/test/CustomConfigurationViaBeansTest.java +++ b/extensions/hibernate-validator/deployment/src/test/java/io/quarkus/hibernate/validator/test/CustomConfigurationViaBeansTest.java @@ -57,9 +57,8 @@ public void testCustomConfigurationViaBeans() { assertThat(hibernateValidatorFactory.getScriptEvaluatorFactory()).isInstanceOf(MyScriptEvaluatorFactory.class); assertThat(hibernateValidatorFactory.getGetterPropertySelectionStrategy()) .isInstanceOf(MyGetterPropertySelectionStrategy.class); - // Waiting for https://hibernate.atlassian.net/browse/HV-1841 to be released - //assertThat(hibernateValidatorFactory.getPropertyNodeNameProvider()) - // .isInstanceOf(MyPropertyNodeNameProvider.class); + assertThat(hibernateValidatorFactory.getPropertyNodeNameProvider()) + .isInstanceOf(MyPropertyNodeNameProvider.class); } @ApplicationScoped diff --git a/extensions/hibernate-validator/runtime/src/main/java/io/quarkus/hibernate/validator/runtime/interceptor/AbstractMethodValidationInterceptor.java b/extensions/hibernate-validator/runtime/src/main/java/io/quarkus/hibernate/validator/runtime/interceptor/AbstractMethodValidationInterceptor.java index b7304743d1e2d..bf4141edb8c0a 100644 --- a/extensions/hibernate-validator/runtime/src/main/java/io/quarkus/hibernate/validator/runtime/interceptor/AbstractMethodValidationInterceptor.java +++ b/extensions/hibernate-validator/runtime/src/main/java/io/quarkus/hibernate/validator/runtime/interceptor/AbstractMethodValidationInterceptor.java @@ -16,6 +16,8 @@ import jakarta.validation.Validator; import jakarta.validation.executable.ExecutableValidator; +import org.hibernate.validator.path.RandomAccessPath; + /** * NOTE: this is a copy of the interceptor present in hibernate-validator-cdi. * For now, I prefer not depending on this artifact but this might change in the @@ -153,6 +155,9 @@ private String getMessage(Member member, Object[] args, Set constraintViolation) { + if (constraintViolation.getPropertyPath() instanceof RandomAccessPath randomAccessPath) { + return randomAccessPath.getLeafNode(); + } Iterator nodes = constraintViolation.getPropertyPath().iterator(); Path.Node leafNode = null; while (nodes.hasNext()) { diff --git a/extensions/hibernate-validator/runtime/src/main/java/io/quarkus/hibernate/validator/runtime/jaxrs/ConstraintTypeUtil20.java b/extensions/hibernate-validator/runtime/src/main/java/io/quarkus/hibernate/validator/runtime/jaxrs/ConstraintTypeUtil20.java index 0ae7e3769718f..1acf858a5ea87 100644 --- a/extensions/hibernate-validator/runtime/src/main/java/io/quarkus/hibernate/validator/runtime/jaxrs/ConstraintTypeUtil20.java +++ b/extensions/hibernate-validator/runtime/src/main/java/io/quarkus/hibernate/validator/runtime/jaxrs/ConstraintTypeUtil20.java @@ -1,49 +1,52 @@ package io.quarkus.hibernate.validator.runtime.jaxrs; -import java.util.Iterator; - import jakarta.validation.ConstraintViolation; import jakarta.validation.ElementKind; import jakarta.validation.Path.Node; +import org.hibernate.validator.path.RandomAccessPath; import org.jboss.resteasy.api.validation.ConstraintType; import org.jboss.resteasy.resteasy_jaxrs.i18n.Messages; import org.jboss.resteasy.spi.validation.ConstraintTypeUtil; public class ConstraintTypeUtil20 implements ConstraintTypeUtil { - @Override - public ConstraintType.Type getConstraintType(Object o) { - if (!(o instanceof ConstraintViolation)) { - throw new RuntimeException(Messages.MESSAGES.unknownObjectPassedAsConstraintViolation(o)); - } - ConstraintViolation v = ConstraintViolation.class.cast(o); - - Iterator nodes = v.getPropertyPath().iterator(); - Node firstNode = nodes.next(); + public static final ConstraintTypeUtil INSTANCE = new ConstraintTypeUtil20(); - switch (firstNode.getKind()) { - case BEAN: - return ConstraintType.Type.CLASS; - case CONSTRUCTOR: - case METHOD: - Node secondNode = nodes.next(); + private ConstraintTypeUtil20() { + } - if (secondNode.getKind() == ElementKind.PARAMETER || secondNode.getKind() == ElementKind.CROSS_PARAMETER) { - return ConstraintType.Type.PARAMETER; - } else if (secondNode.getKind() == ElementKind.RETURN_VALUE) { - return ConstraintType.Type.RETURN_VALUE; - } else { - throw new RuntimeException(Messages.MESSAGES.unexpectedPathNodeViolation(secondNode.getKind())); + @Override + public ConstraintType.Type getConstraintType(Object o) { + if (o instanceof ConstraintViolation v) { + if (v.getPropertyPath() instanceof RandomAccessPath randomAccessPath) { + switch (randomAccessPath.getRootNode().getKind()) { + case BEAN: + return ConstraintType.Type.CLASS; + case CONSTRUCTOR: + case METHOD: + Node secondNode = randomAccessPath.getNode(1); + + if (secondNode.getKind() == ElementKind.PARAMETER + || secondNode.getKind() == ElementKind.CROSS_PARAMETER) { + return ConstraintType.Type.PARAMETER; + } else if (secondNode.getKind() == ElementKind.RETURN_VALUE) { + return ConstraintType.Type.RETURN_VALUE; + } else { + throw new RuntimeException(Messages.MESSAGES.unexpectedPathNodeViolation(secondNode.getKind())); + } + case PROPERTY: + return ConstraintType.Type.PROPERTY; + case CROSS_PARAMETER: + case PARAMETER: + case RETURN_VALUE: + case CONTAINER_ELEMENT: // we shouldn't encounter these element types at the root + default: + throw new RuntimeException( + Messages.MESSAGES.unexpectedPathNode(randomAccessPath.getRootNode().getKind())); } - case PROPERTY: - return ConstraintType.Type.PROPERTY; - case CROSS_PARAMETER: - case PARAMETER: - case RETURN_VALUE: - case CONTAINER_ELEMENT: // we shouldn't encounter these element types at the root - default: - throw new RuntimeException(Messages.MESSAGES.unexpectedPathNode(firstNode.getKind())); + } } + throw new RuntimeException(Messages.MESSAGES.unknownObjectPassedAsConstraintViolation(o)); } } diff --git a/extensions/hibernate-validator/runtime/src/main/java/io/quarkus/hibernate/validator/runtime/jaxrs/ResteasyReactiveViolationExceptionMapper.java b/extensions/hibernate-validator/runtime/src/main/java/io/quarkus/hibernate/validator/runtime/jaxrs/ResteasyReactiveViolationExceptionMapper.java index 1ac209802307d..ca2f676c7da30 100644 --- a/extensions/hibernate-validator/runtime/src/main/java/io/quarkus/hibernate/validator/runtime/jaxrs/ResteasyReactiveViolationExceptionMapper.java +++ b/extensions/hibernate-validator/runtime/src/main/java/io/quarkus/hibernate/validator/runtime/jaxrs/ResteasyReactiveViolationExceptionMapper.java @@ -19,6 +19,7 @@ import jakarta.ws.rs.ext.ExceptionMapper; import jakarta.ws.rs.ext.Provider; +import org.hibernate.validator.path.RandomAccessPath; import org.jboss.resteasy.reactive.common.util.ServerMediaType; import org.jboss.resteasy.reactive.server.core.CurrentRequestManager; import org.jboss.resteasy.reactive.server.core.ResteasyReactiveRequestContext; @@ -57,6 +58,11 @@ private boolean hasReturnValueViolation(Set> violations) } private boolean isReturnValueViolation(ConstraintViolation violation) { + if (violation.getPropertyPath() instanceof RandomAccessPath randomAccessPath) { + return randomAccessPath.getRootNode().getKind() == ElementKind.METHOD + && randomAccessPath.getNode(1).getKind() == ElementKind.RETURN_VALUE; + } + Iterator nodes = violation.getPropertyPath().iterator(); Path.Node firstNode = nodes.next(); diff --git a/extensions/hibernate-validator/runtime/src/main/java/io/quarkus/hibernate/validator/runtime/jaxrs/ResteasyViolationExceptionImpl.java b/extensions/hibernate-validator/runtime/src/main/java/io/quarkus/hibernate/validator/runtime/jaxrs/ResteasyViolationExceptionImpl.java index e79579f5818ff..78e84a9a651e7 100644 --- a/extensions/hibernate-validator/runtime/src/main/java/io/quarkus/hibernate/validator/runtime/jaxrs/ResteasyViolationExceptionImpl.java +++ b/extensions/hibernate-validator/runtime/src/main/java/io/quarkus/hibernate/validator/runtime/jaxrs/ResteasyViolationExceptionImpl.java @@ -1,5 +1,6 @@ package io.quarkus.hibernate.validator.runtime.jaxrs; +import java.io.Serial; import java.util.List; import java.util.Set; @@ -20,6 +21,7 @@ * while a violation on the parameters of a REST endpoint call is a client error (HTTP 400). */ public class ResteasyViolationExceptionImpl extends ResteasyViolationException { + @Serial private static final long serialVersionUID = 657697354453281559L; public ResteasyViolationExceptionImpl(final Set> constraintViolations, @@ -29,7 +31,7 @@ public ResteasyViolationExceptionImpl(final Set @Override public ConstraintTypeUtil getConstraintTypeUtil() { - return new ConstraintTypeUtil20(); + return ConstraintTypeUtil20.INSTANCE; } @Override diff --git a/pom.xml b/pom.xml index 4396a3dc12b97..a6ef62730c8b5 100644 --- a/pom.xml +++ b/pom.xml @@ -77,7 +77,7 @@ 1.17.6 1.0.1 3.1.3.Final - 9.0.1.Final + 9.1.0.Alpha2 8.1.2.Final 7.1.1.Final