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

Hibernate validation fails on a constructor parameter validation #28783

Closed
ivansenic opened this issue Oct 24, 2022 · 26 comments · Fixed by #29094
Closed

Hibernate validation fails on a constructor parameter validation #28783

ivansenic opened this issue Oct 24, 2022 · 26 comments · Fixed by #29094
Assignees
Labels
area/arc Issue related to ARC (dependency injection) area/hibernate-validator Hibernate Validator kind/bug Something isn't working
Milestone

Comments

@ivansenic
Copy link
Contributor

Describe the bug

I am getting a Hibernate exception like the one below when trying to add validation to the bean constructor method like this:

@ApplicationScoped
public class GrpcMetadataResolver {

  @Inject
  public GrpcMetadataResolver(GrpcMetadataConfig config, @SourceApi @Pattern(regexp = "rest|graphql") String sourceApi) {
    ...
  }
}

Removing the @Pattern(regexp = "rest|graphql") makes the injection to work fine.

The stack trace from the cause:

	Caused by: java.lang.IllegalArgumentException: HV000181: Wrong number of parameters. Method or constructor class io.stargate.sgv2.api.common.grpc.GrpcMetadataResolver#GrpcMetadataResolver(GrpcMetadataConfig, String) expects 2 parameters, but got 0.
		at org.hibernate.validator.internal.engine.ValidatorImpl.validateParametersInContext(ValidatorImpl.java:842)
		at org.hibernate.validator.internal.engine.ValidatorImpl.validateParameters(ValidatorImpl.java:283)
		at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstructorParameters(ValidatorImpl.java:243)
		at io.quarkus.hibernate.validator.runtime.interceptor.AbstractMethodValidationInterceptor.validateConstructorInvocation(AbstractMethodValidationInterceptor.java:97)
		at io.quarkus.hibernate.validator.runtime.interceptor.MethodValidationInterceptor.validateConstructorInvocation(MethodValidationInterceptor.java:23)
		at io.quarkus.hibernate.validator.runtime.interceptor.MethodValidationInterceptor_Bean.intercept(Unknown Source)
		at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:42)
		at io.quarkus.arc.impl.LifecycleCallbackInvocationContext.invokeNext(LifecycleCallbackInvocationContext.java:53)
		at io.quarkus.arc.impl.LifecycleCallbackInvocationContext.proceed(LifecycleCallbackInvocationContext.java:28)
		... 202 more

Not sure if there are some config props to handle this behavior? I am sure why would the hibernate go for the no-args constructor here?

Expected behavior

Injection and validation works.

Actual behavior

No response

How to Reproduce?

No response

Output of uname -a or ver

No response

Output of java -version

No response

GraalVM version (if different from Java)

No response

Quarkus version or git rev

2.13.2.Final

Build tool (ie. output of mvnw --version or gradlew --version)

Apache Maven 3.8.4 (9b656c72d54e5bacbed989b64718c159fe39b537) Maven home: /home/ise/.m2/wrapper/dists/apache-maven-3.8.4-bin/52ccbt68d252mdldqsfsn03jlf/apache-maven-3.8.4 Java version: 17.0.4, vendor: Private Build, runtime: /usr/lib/jvm/java-17-openjdk-amd64 Default locale: en_US, platform encoding: UTF-8 OS name: "linux", version: "5.15.0-52-generic", arch: "amd64", family: "unix"

Additional information

No response

@ivansenic ivansenic added the kind/bug Something isn't working label Oct 24, 2022
@quarkus-bot
Copy link

quarkus-bot bot commented Oct 24, 2022

/cc @Sanne, @gsmet, @yrodiere

@quarkus-bot quarkus-bot bot added area/hibernate-orm Hibernate ORM area/persistence OBSOLETE, DO NOT USE labels Oct 24, 2022
@geoand
Copy link
Contributor

geoand commented Oct 24, 2022

Wow, that's very interesting - @gsmet @yrodiere why would HV even be coming into play here?

Also cc @alesj for the gRPC stuff

@ivansenic
Copy link
Contributor Author

Grpc classes are my own, has nothing to do with it.. Should be reproducible with any bean..

@ivansenic
Copy link
Contributor Author

Wow, that's very interesting - @gsmet @yrodiere why would HV even be coming into play here?

Also cc @alesj for the gRPC stuff

It's because of that @Pattern(regexp = "rest|graphql"), it's a validation annotation..

@geoand
Copy link
Contributor

geoand commented Oct 24, 2022

Grpc classes are my own, has nothing to do with it.. Should be reproducible with any bean..

Ah, okay

@geoand geoand added area/hibernate-validator Hibernate Validator and removed area/persistence OBSOLETE, DO NOT USE area/hibernate-orm Hibernate ORM labels Oct 24, 2022
@yrodiere
Copy link
Member

Wow, that's very interesting - @gsmet @yrodiere why would HV even be coming into play here?

Because of @Pattern, a validation annotation.

I'm guessing it's probably Arc doing some bytecode manipulation that ends up replacing/changing constructors? Since there is an @Inject annotation.

I don't think we ever anticipated Hibernate Validator being used on such constructors.

@gsmet
Copy link
Member

gsmet commented Oct 24, 2022

@ivansenic can you please prepare a small Maven reproducer?

I'm pretty sure it has to do with ArC/interceptors/HV interactions. Not sure if we will be able to make it work but having a self contained reproducer would be a good first step.

@gsmet gsmet added the triage/needs-reproducer We are waiting for a reproducer. label Oct 24, 2022
@ivansenic
Copy link
Contributor Author

ivansenic commented Oct 24, 2022

Will create one at some point this week..

@gsmet
Copy link
Member

gsmet commented Nov 7, 2022

@ivansenic friendly ping.

@ivansenic
Copy link
Contributor Author

@ivansenic friendly ping.

Yea, forgot about this, will provide the reproducer by the end of the day.

@ivansenic
Copy link
Contributor Author

@gsmet Here it is: https://github.com/ivansenic/quarkus-28783

Hit curl http://localhost:8080/hello and you will get the same exception as above:

2022-11-07 11:52:55,896 ERROR [io.qua.ver.htt.run.QuarkusErrorHandler] (executor-thread-0) HTTP Request to /hello failed, error id: c36ebd62-044d-4520-808b-e59da59c90e5-1: java.lang.RuntimeException: Error invoking aroundConstructs
	at org.acme.GreetingResource_Bean.create(Unknown Source)
	at org.acme.GreetingResource_Bean.create(Unknown Source)
	at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:113)
	at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:37)
	at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:34)
	at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26)
	at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69)
	at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:34)
	at org.acme.GreetingResource_Bean.get(Unknown Source)
	at org.acme.GreetingResource_Bean.get(Unknown Source)
	at io.quarkus.arc.impl.ArcContainerImpl.beanInstanceHandle(ArcContainerImpl.java:471)
	at io.quarkus.arc.impl.ArcContainerImpl.beanInstanceHandle(ArcContainerImpl.java:484)
	at io.quarkus.arc.impl.ArcContainerImpl$1.get(ArcContainerImpl.java:288)
	at io.quarkus.arc.impl.ArcContainerImpl$1.get(ArcContainerImpl.java:285)
	at io.quarkus.arc.runtime.BeanContainerImpl$1.create(BeanContainerImpl.java:36)
	at io.quarkus.resteasy.reactive.common.runtime.ArcBeanFactory.createInstance(ArcBeanFactory.java:27)
	at org.jboss.resteasy.reactive.server.handlers.InstanceHandler.handle(InstanceHandler.java:26)
	at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:113)
	at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:142)
	at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:564)
	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
	at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
	at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.IllegalArgumentException: HV000181: Wrong number of parameters. Method or constructor class org.acme.GreetingResource#GreetingResource(String) expects 1 parameters, but got 0.
	at org.hibernate.validator.internal.engine.ValidatorImpl.validateParametersInContext(ValidatorImpl.java:842)
	at org.hibernate.validator.internal.engine.ValidatorImpl.validateParameters(ValidatorImpl.java:283)
	at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstructorParameters(ValidatorImpl.java:243)
	at io.quarkus.hibernate.validator.runtime.interceptor.AbstractMethodValidationInterceptor.validateConstructorInvocation(AbstractMethodValidationInterceptor.java:97)
	at io.quarkus.hibernate.validator.runtime.interceptor.MethodValidationInterceptor.validateConstructorInvocation(MethodValidationInterceptor.java:23)
	at io.quarkus.hibernate.validator.runtime.interceptor.MethodValidationInterceptor_Bean.intercept(Unknown Source)
	at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:42)
	at io.quarkus.arc.impl.LifecycleCallbackInvocationContext.invokeNext(LifecycleCallbackInvocationContext.java:53)
	at io.quarkus.arc.impl.LifecycleCallbackInvocationContext.proceed(LifecycleCallbackInvocationContext.java:28)
	... 26 more

@geoand
Copy link
Contributor

geoand commented Nov 7, 2022

This looks like a bug in Arc because when the code reaches here, javax.interceptor.InvocationContext returns the following:

ctx.getConstructor(): public org.acme.GreetingResource(java.lang.String)
ctx.getParameters(): Object[0]

So we need to rope in @mkouba and/or @manovotn

@geoand geoand removed the triage/needs-reproducer We are waiting for a reproducer. label Nov 7, 2022
@manovotn
Copy link
Contributor

manovotn commented Nov 7, 2022

Hm, GreetingResource is going to be a normal-scoped bean, right? Something that requires a proxy (i.e. application scoped).
In that case, we might be generating an extra no-args constructor in order to be able to create the proxy.

I'll take a look

@geoand geoand added the area/arc Issue related to ARC (dependency injection) label Nov 7, 2022
@geoand
Copy link
Contributor

geoand commented Nov 7, 2022

I'll take a look

Thanks

@manovotn
Copy link
Contributor

manovotn commented Nov 7, 2022

Actually, it seems we just don't pass around c-tor params correctly into invocation context for this scenario.
In fact, it seems that there params will always be empty for around construct interception.
Looking here, those params will always be null.

@geoand
Copy link
Contributor

geoand commented Nov 7, 2022

Looking here, those params will always be null

Yeah I saw during debugging but was not sure why it was happening :)

@manovotn
Copy link
Contributor

manovotn commented Nov 7, 2022

I think it is either an oversight or just a simple initial version of the code that wasn't discovered to be insufficient until now :)

@geoand
Copy link
Contributor

geoand commented Nov 7, 2022

Understood, thanks :).

I was kinda thrown off because we usually some kind of TODO (I've seen them in Arc as well over the years), so I was not sure what was going on.

@manovotn
Copy link
Contributor

manovotn commented Nov 7, 2022

I've sent #29094 as an attempt to fix this.

@quarkus-bot quarkus-bot bot added this to the 2.15 - main milestone Nov 8, 2022
@ivansenic
Copy link
Contributor Author

Wow this was fixed fast 🚀

@gsmet gsmet modified the milestones: 2.15 - main, 2.14.1.Final Nov 10, 2022
@Sanne Sanne changed the title HIbernate validation fails on a constructor parameter validation Hibernate validation fails on a constructor parameter validation Nov 17, 2022
@luca-bassoricci
Copy link
Contributor

I'm still having the same error, but with augmented arguments.(#29322 (comment))

@manovotn
Copy link
Contributor

@luca-bassoricci can you please create a new issue and attach a reproducer?

@luca-bassoricci
Copy link
Contributor

luca-bassoricci commented Nov 18, 2022

issue-28783.zip
I have uploaded a reproducer
Error is

java.lang.RuntimeException: Error invoking aroundConstructs
	at org.acme.Service_Bean.create(Unknown Source)
	at org.acme.Service_Bean.create(Unknown Source)
	at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:113)
	at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:37)
	at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:34)
	at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26)
	at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69)
	at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:34)
	at io.quarkus.arc.impl.ClientProxies.getApplicationScopedDelegate(ClientProxies.java:21)
	at org.acme.Service_ClientProxy.arc$delegate(Unknown Source)
	at org.acme.Service_ClientProxy.txMethod(Unknown Source)
	at org.acme.GreetingResource.hello(GreetingResource.java:25)
	at org.acme.GreetingResource$quarkusrestinvoker$hello_e747664148511e1e5212d3e0f4b40d45c56ab8a1.invoke(Unknown Source)
	at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
	at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:114)
	at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:145)
	at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:576)
	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
	at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
	at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.IllegalArgumentException: HV000181: Wrong number of parameters. Method or constructor class org.acme.Service#Service(ApplicationConfig) expects 1 parameters, but got 3.
	at org.hibernate.validator.internal.engine.ValidatorImpl.validateParametersInContext(ValidatorImpl.java:842)
	at org.hibernate.validator.internal.engine.ValidatorImpl.validateParameters(ValidatorImpl.java:283)
	at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstructorParameters(ValidatorImpl.java:243)
	at io.quarkus.hibernate.validator.runtime.interceptor.AbstractMethodValidationInterceptor.validateConstructorInvocation(AbstractMethodValidationInterceptor.java:97)
	at io.quarkus.hibernate.validator.runtime.interceptor.MethodValidationInterceptor.validateConstructorInvocation(MethodValidationInterceptor.java:23)
	at io.quarkus.hibernate.validator.runtime.interceptor.MethodValidationInterceptor_Bean.intercept(Unknown Source)
	at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:42)
	at io.quarkus.arc.impl.LifecycleCallbackInvocationContext.invokeNext(LifecycleCallbackInvocationContext.java:53)
	at io.quarkus.arc.impl.LifecycleCallbackInvocationContext.proceed(LifecycleCallbackInvocationContext.java:28)
	... 23 more

Removing @Transactional from org.acme.Service#txMethod() get rid of the problem

@manovotn

@manovotn
Copy link
Contributor

Thanks, I'll take a look at it today or tomorrow.

@manovotn
Copy link
Contributor

So the paramers I am seeing passed into that constructor are:

  • ApplicationConfig (this is the expected param)
  • InitializedInterceptor (the around construct interceptor instance; in the reproducer this is the HV interceptor instance)
  • TransactionalInterceptorRequired (around invoke interceptor; in the reproducer it's JTA interceptor linked with @Transactional)

From a quick glance at the code, this happens because as soon as there is an around invoke interceptor, we need to create a subclass and this subclass has InjectableInterceptor of all linked intercpetors as its parameters on top of whatever it had before.
We could look into how to hide these params from InvocationContext and only pass the original ones.
WDYT @mkouba ?

As a side note - this can be easily reproduced by using existing test and adding an around invoke interceptor to the SimpleBean class.

@mkouba
Copy link
Contributor

mkouba commented Nov 23, 2022

WDYT?

I need to look at the generated code.

As a side note - this can be easily reproduced by using existing test and adding an around invoke interceptor to the SimpleBean class.

Like adding an @AroundConstruct callback to the SimpleBean? I believe that this should not be supported.

Ok, I got it - you mean just intecept a SimpleBean method with an @AroundInvoke interceptor.

@gsmet gsmet modified the milestones: 2.14.1.Final, 2.13.6.Final Dec 14, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/arc Issue related to ARC (dependency injection) area/hibernate-validator Hibernate Validator kind/bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants