Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding javax.validation @Valid in JAX-RS resource method which override an interface break HibernateValidatorTemplate #2556

Closed
masini opened this issue May 22, 2019 · 5 comments
Assignees
Labels
area/hibernate-validator Hibernate Validator kind/bug Something isn't working
Milestone

Comments

@masini
Copy link
Contributor

masini commented May 22, 2019

Describe the bug

I have an interface with a single method:

public interface GreetingResourceInterface<T> {
    String hello(T pojo);
}

and a JAX-RS resource which implements it:

@Path("/hello")
public class GreetingResource implements GreetingResourceInterface<MyPojo> {

    @Override
    @POST
    @Produces(MediaType.TEXT_PLAIN)
    @Consumes(MediaType.APPLICATION_JSON)
    public String hello(@Valid MyPojo pojo) {
        return "hello";
    }
}

Expected behavior

The parameter is "validated" with javax.validation.

Actual behavior

At startup with:

mvn clean compile quarkus:dev

I got this Exception:

14:02:18,137 ERROR [io.qua.dev.DevModeMain] Failed to start quarkus: java.lang.ExceptionInInitializerError
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
        at java.lang.Class.newInstance(Class.java:442)
        at io.quarkus.runner.RuntimeRunner.run(RuntimeRunner.java:121)
        at io.quarkus.dev.DevModeMain.doStart(DevModeMain.java:159)
        at io.quarkus.dev.DevModeMain.main(DevModeMain.java:93)
Caused by: java.lang.RuntimeException: Failed to start quarkus
        at io.quarkus.runner.ApplicationImpl1.<clinit>(Unknown Source)
        ... 8 more
Caused by: java.lang.ArrayIndexOutOfBoundsException: 1
        at org.hibernate.validator.internal.properties.javabean.JavaBeanExecutable.getParameters(JavaBeanExecutable.java:213)
        at org.hibernate.validator.internal.properties.javabean.JavaBeanExecutable.<init>(JavaBeanExecutable.java:45)
        at org.hibernate.validator.internal.properties.javabean.JavaBeanConstructor.<init>(JavaBeanConstructor.java:20)
        at org.hibernate.validator.internal.properties.javabean.JavaBeanHelper.executable(JavaBeanHelper.java:109)
        at org.hibernate.validator.internal.properties.javabean.JavaBeanHelper.executable(JavaBeanHelper.java:104)
        at org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider.findExecutableMetaData(AnnotationMetaDataProvider.java:307)
        at org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider.getMetaData(AnnotationMetaDataProvider.java:292)
        at org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider.getConstructorMetaData(AnnotationMetaDataProvider.java:273)
        at org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider.retrieveBeanConfiguration(AnnotationMetaDataProvider.java:131)
        at org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider.getBeanConfiguration(AnnotationMetaDataProvider.java:120)
        at org.hibernate.validator.internal.metadata.PredefinedScopeBeanMetaDataManager.getBeanConfigurationForHierarchy(PredefinedScopeBeanMetaDataManager.java:165)
        at org.hibernate.validator.internal.metadata.PredefinedScopeBeanMetaDataManager.createBeanMetaData(PredefinedScopeBeanMetaDataManager.java:132)
        at org.hibernate.validator.internal.metadata.PredefinedScopeBeanMetaDataManager.<init>(PredefinedScopeBeanMetaDataManager.java:83)
        at org.hibernate.validator.internal.engine.PredefinedScopeValidatorFactoryImpl.<init>(PredefinedScopeValidatorFactoryImpl.java:175)
        at org.hibernate.validator.PredefinedScopeHibernateValidator.buildValidatorFactory(PredefinedScopeHibernateValidator.java:42)
        at org.hibernate.validator.internal.engine.AbstractConfigurationImpl.buildValidatorFactory(AbstractConfigurationImpl.java:369)
        at io.quarkus.hibernate.validator.runtime.HibernateValidatorTemplate.initializeValidatorFactory(HibernateValidatorTemplate.java:56)
        at io.quarkus.deployment.steps.HibernateValidatorProcessor$build6.deploy(Unknown Source)
        ... 9 more

When the executable of the:

org.hibernate.validator.internal.properties.javabean.JavaBeanExecutable.getParameters(java.lang.reflect.Executable) 

method is:

io.smallrye.config.ConfigSourceMap$EntrySet$Itr(io.smallrye.config.ConfigSourceMap$EntrySet,java.util.Iterator)

it does a bad calculation of "explicitlyDeclaredParameterIndex", accessing to the genericParameterTypes array with index[1] raise the
Exception.

To Reproduce

Steps to reproduce the behavior:

  1. Unzip the attached test-case
  2. mvn clean compile quarkus:dev

Configuration

None

Environment (please complete the following information):

  • Output of uname -a or ver:

    Darwin WMICTLM1P.local 18.6.0 Darwin Kernel Version 18.6.0: Thu Apr 25 23:16:27 PDT 2019; root:xnu-4903.261.4~2/RELEASE_X86_64 x86_64

  • Output of java -version:

    java version "1.8.0_152"

  • Quarkus version or git rev:

    0.15.0

Additional context
The same exact problem can be replicated from the attached test-case.

There is another issue with javax.validation and Interface, but in own opinion is not related:

#1888

test-case.zip

@masini masini added the kind/bug Something isn't working label May 22, 2019
@masini masini changed the title Adding javax.validation @Valid in JAX-RS resource method which override an interface break ARC Adding javax.validation @Valid in JAX-RS resource method which override an interface break HibernateValidatorTemplate May 22, 2019
@Sanne Sanne added the area/hibernate-validator Hibernate Validator label May 23, 2019
@gsmet
Copy link
Member

gsmet commented May 30, 2019

I can confirm this is not fixed in current master.

@gsmet gsmet self-assigned this May 30, 2019
@gsmet gsmet added this to the 0.17.0 milestone May 30, 2019
@gsmet gsmet modified the milestones: 0.17.0, 0.18.0, 0.19.0 Jun 19, 2019
@gsmet gsmet added this to To do in Quarkus 1.0.0 Planning via automation Jul 3, 2019
@gsmet gsmet modified the milestones: 0.19.0, 0.20.0 Jul 9, 2019
@gsmet gsmet modified the milestones: 0.20.0, 0.21.0 Jul 31, 2019
@gsmet gsmet modified the milestones: 0.21.0, 0.22.0 Aug 14, 2019
@gsmet gsmet modified the milestones: 0.22.0, 0.23.0 Aug 28, 2019
@FroMage
Copy link
Member

FroMage commented Oct 4, 2019

This is a bug in HV, though, no @gsmet ?

@gsmet
Copy link
Member

gsmet commented Oct 4, 2019

It's a bug in HV and we have a PR open to fix it. But let's keep that open as I need the test case handy.

@gsmet gsmet modified the milestones: 0.24.0, 0.25.0 Oct 9, 2019
@gsmet gsmet added this to To do in Deprecated - Quarkus 1.0 via automation Oct 9, 2019
@yrodiere yrodiere self-assigned this Oct 9, 2019
@yrodiere
Copy link
Member

yrodiere commented Oct 9, 2019

Several comments here:

  1. This is definitely caused by a bug in HV, namely HV-1730. The pending PR here fixes the problem.
  2. For some reason, the bug only occurs if the method with the annotated parameter is declared in a superinterface. If the method is declared directly in the implementing class, the bug does not occur.
  3. The @Valid annotation is irrelevant. @Digits on a parameter of type Integer (T extends Number in the superinterface) triggers the bug as well.
  4. @POST is irrelevant. The bug is triggered on a @GET method with path-params as well.
  5. Even when the bug is fixed, the code in the given test case is invalid, because the implementation of the REST endpoint adds constraints compared to the generic interface. Hibernate Validator forbids this, and will throw an exception similar to this:
Caused by: javax.validation.ConstraintDeclarationException: HV000151: A method overriding another method must not redefine the parameter constraint configuration, but method HibernateValidatorTestResource#testRestEndpointGenericMethodValidation(MyPojo) redefines the configuration of HibernateValidatorTestResourceGenericInterface#testRestEndpointGenericMethodValidation(Object).
  1. Not really related, but the implementing class has to set the @Valid annotation too in order for validation to occur. Otherwise, the @Valid annotation from the superinterface is ignored.
  2. In this particular case, the bug occurs while Hibernate Validator inspects class io.smallrye.config.ConfigSourceMap$Values$Itr, which does not appear in the user code. I wonder why Hibernate Validator inspects this class in the first place?

@gsmet I thing item 7 warrants further investigation. I added a test to my PR here: #4439
In that test, org.hibernate.validator.internal.metadata.PredefinedScopeBeanMetaDataManager#PredefinedScopeBeanMetaDataManager gets called with the following classes in beanClassesToInitialize. That seems a bit much?

0 = {Class@4376} "class io.smallrye.config.Converters$ArrayConverter"
1 = {Class@4360} "class io.quarkus.test.common.http.URLTestHTTPResourceProvider"
2 = {Class@2972} "class io.smallrye.config.SmallRyeConfigBuilder"
3 = {Class@3033} "class io.smallrye.config.SmallRyeConfig$1"
4 = {Class@4347} "class io.smallrye.config.inject.ConfigProducerUtil"
5 = {Class@4339} "class io.quarkus.it.hibernate.validator.custom.MyOtherBean"
6 = {Class@4364} "class io.smallrye.config.ImplicitConverters$StaticMethodConverter$Serialized"
7 = {Class@4372} "class io.quarkus.test.common.NativeImageLauncher$ProcessReader"
8 = {Class@4365} "class io.quarkus.test.common.http.StringTestHTTPResourceProvider"
9 = {Class@4379} "class io.quarkus.test.common.NativeImageLauncher"
10 = {Class@4340} "class io.quarkus.test.common.TestScopeManager"
11 = {Class@4344} "class io.smallrye.config.inject.ConfigInjectionBean$InjectionPointMetadataInjectionPoint"
12 = {Class@3027} "class io.smallrye.config.EnvConfigSource"
13 = {Class@4331} "interface io.quarkus.it.hibernate.validator.HibernateValidatorTestResourceGenericInterface"
14 = {Class@4378} "class io.smallrye.config.ConfigSourceMap$Values$Itr"
15 = {Class@3032} "class io.smallrye.config.SmallRyeConfig"
16 = {Class@4346} "class io.quarkus.test.common.http.TestHTTPResourceManager"
17 = {Class@4345} "class io.quarkus.it.hibernate.validator.HibernateValidatorTestResource$MyBean"
18 = {Class@4377} "class io.smallrye.config.Converters$RangeCheckConverter"
19 = {Class@3029} "class io.smallrye.config.PropertiesConfigSourceProvider"
20 = {Class@4369} "class io.quarkus.it.hibernate.validator.injection.MyService"
21 = {Class@2119} "class io.quarkus.test.common.PropertyTestUtil"
22 = {Class@3070} "class io.smallrye.config.ImplicitConverters$ConstructorConverter"
23 = {Class@2247} "class io.quarkus.test.common.QuarkusTestResourceLifecycleManagerComparator"
24 = {Class@4329} "class io.quarkus.it.hibernate.validator.HibernateValidatorTestResource$NestedBeanWithoutConstraints"
25 = {Class@2158} "class io.quarkus.test.common.TestResourceManager"
26 = {Class@4366} "class io.quarkus.test.common.TestInstantiator"
27 = {Class@4334} "class io.quarkus.it.hibernate.validator.custom.MyCustomConstraint$Validator"
28 = {Class@4352} "class io.smallrye.config.inject.ConfigInjectionBean"
29 = {Class@4382} "class io.smallrye.config.inject.ConfigExtension"
30 = {Class@4368} "class io.smallrye.config.ConfigSourceMap$EntrySet$Itr"
31 = {Class@4330} "class io.quarkus.it.hibernate.validator.HibernateValidatorTestResource$BeanWithInjectedConstraintValidatorConstraint"
32 = {Class@2161} "class io.quarkus.test.common.PathTestHelper"
33 = {Class@4375} "class io.quarkus.it.hibernate.validator.HibernateValidatorTestResource$1"
34 = {Class@3028} "class io.smallrye.config.SysPropConfigSource"
35 = {Class@2991} "class io.smallrye.config.Converters$BuiltInConverter"
36 = {Class@4374} "class io.smallrye.config.DirConfigSource"
37 = {Class@4335} "class io.smallrye.config.Converters$PatternCheckConverter"
38 = {Class@4362} "class io.quarkus.test.common.NativeImageLauncher$1"
39 = {Class@4370} "class io.quarkus.it.hibernate.validator.GreetingService"
40 = {Class@4380} "class io.quarkus.test.common.TestInjectionManager"
41 = {Class@4357} "class io.quarkus.it.hibernate.validator.injection.InjectedConstraintValidator"
42 = {Class@327} "class java.lang.Object"
43 = {Class@4361} "class io.smallrye.config.inject.ConfigProducer"
44 = {Class@4328} "class io.quarkus.it.hibernate.validator.HibernateValidatorTestResource$ResultBuilder"
45 = {Class@2989} "class io.smallrye.config.Converters"
46 = {Class@4336} "class io.smallrye.config.ImplicitConverters$ConstructorConverter$Serialized"
47 = {Class@3802} "class io.smallrye.config.ImplicitConverters$StaticMethodConverter"
48 = {Class@1200} "class io.quarkus.it.hibernate.validator.HibernateValidatorFunctionalityTest"
49 = {Class@4332} "class io.quarkus.it.hibernate.validator.HibernateValidatorTestResource"
50 = {Class@4338} "class io.smallrye.config.SmallRyeConfigBuilder$1"
51 = {Class@4371} "class io.quarkus.test.common.http.URITestHTTPResourceProvider"
52 = {Class@4358} "class io.quarkus.it.hibernate.validator.HibernateValidatorFunctionalityInGraalITCase"
53 = {Class@2166} "class io.quarkus.test.common.TestResourceManager$1"
54 = {Class@2982} "class io.smallrye.config.PropertiesConfigSource"
55 = {Class@1593} "class io.quarkus.test.common.RestAssuredURLManager"
56 = {Class@3562} "class io.smallrye.config.SecuritySupport"
57 = {Class@4373} "class io.smallrye.config.Converters$CollectionConverter"
58 = {Class@3069} "class io.smallrye.config.ImplicitConverters"
59 = {Class@4367} "class io.smallrye.config.Converters$Ser"
60 = {Class@4363} "class io.smallrye.config.inject.ConfigInjectionBean$1"
61 = {Class@4337} "class io.quarkus.it.hibernate.validator.pojo.MyPojo"
62 = {Class@3061} "class io.smallrye.config.StringUtil"
63 = {Class@3016} "class io.smallrye.config.SmallRyeConfigBuilder$ConverterWithPriority"

@gsmet
Copy link
Member

gsmet commented Oct 9, 2019

Urgh, that's definitely not intended... well, except if the classes are annotated with BV/HV annotations. I'll have a closer look as soon as I can.

@gsmet gsmet modified the milestones: 0.26.0, 0.27.0 Oct 15, 2019
gsmet added a commit that referenced this issue Oct 29, 2019
@gsmet gsmet closed this as completed Oct 29, 2019
Deprecated - Quarkus 1.0 automation moved this from To do to Done Oct 29, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/hibernate-validator Hibernate Validator kind/bug Something isn't working
Projects
No open projects
Development

No branches or pull requests

5 participants