From f6cffe0efdf4215ce09da17d801265905075e4ef Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 27 May 2021 10:03:54 +0200 Subject: [PATCH] Hibernate Validator - Work around Jandex issue in enclosingTarget() This is not ideal and we will need a better fix in Jandex but for now we need a quick workaround. Workaround for #17491 --- .../HibernateValidatorProcessor.java | 49 ++++++++++++------- .../test/ContainerElementConstraintsTest.java | 15 ++++++ 2 files changed, 45 insertions(+), 19 deletions(-) diff --git a/extensions/hibernate-validator/deployment/src/main/java/io/quarkus/hibernate/validator/deployment/HibernateValidatorProcessor.java b/extensions/hibernate-validator/deployment/src/main/java/io/quarkus/hibernate/validator/deployment/HibernateValidatorProcessor.java index 5509ef44580a4..e331c6deadc3d 100644 --- a/extensions/hibernate-validator/deployment/src/main/java/io/quarkus/hibernate/validator/deployment/HibernateValidatorProcessor.java +++ b/extensions/hibernate-validator/deployment/src/main/java/io/quarkus/hibernate/validator/deployment/HibernateValidatorProcessor.java @@ -273,26 +273,37 @@ public void build(HibernateValidatorRecorder recorder, RecorderContext recorderC contributeClass(classNamesToBeValidated, indexView, annotation.target().asClass().name()); // no need for reflection in the case of a class level constraint } else if (annotation.target().kind() == AnnotationTarget.Kind.TYPE) { - // container element constraints - AnnotationTarget enclosingTarget = annotation.target().asType().enclosingTarget(); - if (enclosingTarget.kind() == AnnotationTarget.Kind.FIELD) { - contributeClass(classNamesToBeValidated, indexView, enclosingTarget.asField().declaringClass().name()); - reflectiveFields.produce(new ReflectiveFieldBuildItem(enclosingTarget.asField())); - if (annotation.target().asType().target() != null) { - contributeClassMarkedForCascadingValidation(classNamesToBeValidated, indexView, - consideredAnnotation, - annotation.target().asType().target()); + // there is a bug in Jandex regarding enclosingTarget() when annotations are on constructors located in a separate indexed library + // (enclosing target is a ClassInfo instead of a MethodInfo and enclosingTarget() tries to catch it to a MethodInfo + // leading to a ClassCastException) + // for now we swallow the exception, pending a bugfix in Jandex + // see https://github.com/quarkusio/quarkus/issues/17491 + try { + // container element constraints + AnnotationTarget enclosingTarget = annotation.target().asType().enclosingTarget(); + if (enclosingTarget.kind() == AnnotationTarget.Kind.FIELD) { + contributeClass(classNamesToBeValidated, indexView, + enclosingTarget.asField().declaringClass().name()); + reflectiveFields.produce(new ReflectiveFieldBuildItem(enclosingTarget.asField())); + if (annotation.target().asType().target() != null) { + contributeClassMarkedForCascadingValidation(classNamesToBeValidated, indexView, + consideredAnnotation, + annotation.target().asType().target()); + } + } else if (enclosingTarget.kind() == AnnotationTarget.Kind.METHOD) { + contributeClass(classNamesToBeValidated, indexView, + enclosingTarget.asMethod().declaringClass().name()); + reflectiveMethods.produce(new ReflectiveMethodBuildItem(enclosingTarget.asMethod())); + if (annotation.target().asType().target() != null) { + contributeClassMarkedForCascadingValidation(classNamesToBeValidated, indexView, + consideredAnnotation, + annotation.target().asType().target()); + } + contributeMethodsWithInheritedValidation(methodsWithInheritedValidation, indexView, + enclosingTarget.asMethod()); } - } else if (enclosingTarget.kind() == AnnotationTarget.Kind.METHOD) { - contributeClass(classNamesToBeValidated, indexView, enclosingTarget.asMethod().declaringClass().name()); - reflectiveMethods.produce(new ReflectiveMethodBuildItem(enclosingTarget.asMethod())); - if (annotation.target().asType().target() != null) { - contributeClassMarkedForCascadingValidation(classNamesToBeValidated, indexView, - consideredAnnotation, - annotation.target().asType().target()); - } - contributeMethodsWithInheritedValidation(methodsWithInheritedValidation, indexView, - enclosingTarget.asMethod()); + } catch (Exception e) { + // ignore } } } diff --git a/extensions/hibernate-validator/deployment/src/test/java/io/quarkus/hibernate/validator/test/ContainerElementConstraintsTest.java b/extensions/hibernate-validator/deployment/src/test/java/io/quarkus/hibernate/validator/test/ContainerElementConstraintsTest.java index 47771618c4154..cc043deda8fcb 100644 --- a/extensions/hibernate-validator/deployment/src/test/java/io/quarkus/hibernate/validator/test/ContainerElementConstraintsTest.java +++ b/extensions/hibernate-validator/deployment/src/test/java/io/quarkus/hibernate/validator/test/ContainerElementConstraintsTest.java @@ -55,6 +55,14 @@ public void testMethodReturnValueContainerElementConstraint() throws NoSuchMetho MethodReturnValueTestBean.class.getMethod("test"), invalidMap)).hasSize(1); } + @Test + public void testConstructorParameterContainerElementConstraint() throws NoSuchMethodException, SecurityException { + List invalidList = Collections.singletonList(""); + + assertThat(validatorFactory.getValidator().forExecutables().validateConstructorParameters( + ConstructorParameterTestBean.class.getConstructor(List.class), new Object[] { invalidList })).hasSize(1); + } + static class TestBean { public Map constrainedMap; @@ -92,4 +100,11 @@ static class MethodReturnValueTestBean { return null; } } + + static class ConstructorParameterTestBean { + + public ConstructorParameterTestBean(List<@NotBlank String> constrainedList) { + // do nothing + } + } }