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

Upgrading to 2.14 breaks REST resources (potentially because of BeanParam) #29227

Closed
kjq opened this issue Nov 12, 2022 · 24 comments · Fixed by #29355
Closed

Upgrading to 2.14 breaks REST resources (potentially because of BeanParam) #29227

kjq opened this issue Nov 12, 2022 · 24 comments · Fixed by #29355
Assignees
Labels
area/rest kind/bug Something isn't working
Milestone

Comments

@kjq
Copy link

kjq commented Nov 12, 2022

Describe the bug

Upgrading from 2.13.4 (everything working/tests run) to 2.14 and have run into an issue it appears with the @BeanParams. This prevents us from upgrading other dependencies such as Stork and Helm as well as being able to take advantage of some nice enhancements in 2.14.

There looks to be two issues but they might be related.

  1. Implementing an interface from a REST client in a resource and the method takes in a payload uses @BeanParam throws an exception at build time.

[ERROR] Caused by: javax.enterprise.inject.spi.DeploymentException: No annotations found on fields at 'companyx.api.feature.Feature'. Annotations like @QueryParam should be used in fields, not in methods.

[ERROR]         [error]: Build step io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#setupEndpoints threw an exception: java.lang.RuntimeException: java.lang.RuntimeException: Failed to process method 'companyx.api.feature.FeatureClient#save'
[ERROR]         at org.jboss.resteasy.reactive.common.processor.EndpointIndexer.createEndpoints(EndpointIndexer.java:318)
[ERROR]         at io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor.setupEndpoints(ResteasyReactiveProcessor.java:613)
[ERROR]         at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[ERROR]         at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
[ERROR]         at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[ERROR]         at java.base/java.lang.reflect.Method.invoke(Method.java:568)
[ERROR]         at io.quarkus.deployment.ExtensionLoader$3.execute(ExtensionLoader.java:909)
[ERROR]         at io.quarkus.builder.BuildContext.run(BuildContext.java:281)
[ERROR]         at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
[ERROR]         at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
[ERROR]         at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
[ERROR]         at java.base/java.lang.Thread.run(Thread.java:833)
[ERROR]         at org.jboss.threads.JBossThread.run(JBossThread.java:501)
[ERROR] Caused by: java.lang.RuntimeException: Failed to process method 'companyx.api.feature.FeatureClient#save'
[ERROR]         at org.jboss.resteasy.reactive.common.processor.EndpointIndexer.createResourceMethod(EndpointIndexer.java:710)
[ERROR]         at org.jboss.resteasy.reactive.common.processor.EndpointIndexer.createEndpoints(EndpointIndexer.java:408)
[ERROR]         at org.jboss.resteasy.reactive.common.processor.EndpointIndexer.createEndpoints(EndpointIndexer.java:455)
[ERROR]         at org.jboss.resteasy.reactive.common.processor.EndpointIndexer.createEndpoints(EndpointIndexer.java:289)
[ERROR]         ... 12 more
[ERROR] Caused by: javax.enterprise.inject.spi.DeploymentException: No annotations found on fields at 'companyx.api.feature.Feature'. Annotations like `@QueryParam` should be used in fields, not in methods.
[ERROR]         at org.jboss.resteasy.reactive.server.processor.ServerEndpointIndexer.handleBeanParam(ServerEndpointIndexer.java:185)
[ERROR]         at org.jboss.resteasy.reactive.common.processor.EndpointIndexer.createResourceMethod(EndpointIndexer.java:568)
[ERROR]         ... 15 more
  1. Running with tests, and this is a simple test I get this issue:

Caused by: javax.enterprise.inject.AmbiguousResolutionException: Beans: [CLASS bean [class=companyx.api.project.ProjectParams, id=9fbe6c147b4e4613d0947934fb37c85f9738382b], CLASS bean [class=companyx.api.storage.AssetParams, id=200da7b2e76e0435661fa5435234030fd029f6f6], CLASS bean [class=companyx.api.artifact.ArtifactParams, id=ccde4a7e2f9460f415624c81466a3936ac3253d7], CLASS bean [class=companyx.api.query.RowParams, id=fef36db73899ee70ae3eed9ab9975fc01852e211]]

[ERROR] companyx.api.artifact.ArtifactParamTest.should_have_all_args  Time elapsed: 0.008 s  <<< ERROR!
java.lang.RuntimeException: java.lang.ExceptionInInitializerError
        at io.quarkus.test.junit.QuarkusTestExtension.throwBootFailureException(QuarkusTestExtension.java:625)
        at io.quarkus.test.junit.QuarkusTestExtension.interceptTestClassConstructor(QuarkusTestExtension.java:696)
        at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
        at org.junit.jupiter.api.extension.InvocationInterceptor.interceptTestClassConstructor(InvocationInterceptor.java:73)
        at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
        at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
        at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:62)
        at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestClassConstructor(ClassBasedTestDescriptor.java:363)
        at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateTestClass(ClassBasedTestDescriptor.java:310)
        at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.instantiateTestClass(ClassTestDescriptor.java:79)
        at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:286)
        at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$4(ClassBasedTestDescriptor.java:278)
        at java.base/java.util.Optional.orElseGet(Optional.java:364)
        at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$5(ClassBasedTestDescriptor.java:277)
        at org.junit.jupiter.engine.execution.TestInstancesProvider.getTestInstances(TestInstancesProvider.java:31)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$prepare$0(TestMethodTestDescriptor.java:105)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:104)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:68)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$2(NodeTestTask.java:123)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:123)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:90)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
        at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
        at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
        at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
        at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
        at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:55)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
        at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
        at org.apache.maven.surefire.junitplatform.LazyLauncher.execute(LazyLauncher.java:55)
        at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.execute(JUnitPlatformProvider.java:223)
        at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invokeAllTests(JUnitPlatformProvider.java:175)
        at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invoke(JUnitPlatformProvider.java:139)
        at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:456)
        at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:169)
        at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:595)
        at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:581)
Caused by: java.lang.ExceptionInInitializerError
        at java.base/java.lang.Class.forName0(Native Method)
        at java.base/java.lang.Class.forName(Class.java:467)
        at io.quarkus.runner.bootstrap.StartupActionImpl.run(StartupActionImpl.java:237)
        at io.quarkus.test.junit.QuarkusTestExtension.doJavaStart(QuarkusTestExtension.java:250)
        at io.quarkus.test.junit.QuarkusTestExtension.ensureStarted(QuarkusTestExtension.java:592)
        at io.quarkus.test.junit.QuarkusTestExtension.beforeAll(QuarkusTestExtension.java:640)
        at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeBeforeAllCallbacks$12(ClassBasedTestDescriptor.java:395)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeBeforeAllCallbacks(ClassBasedTestDescriptor.java:395)
        at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:211)
        at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:84)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:148)
        ... 37 more
Caused by: java.lang.RuntimeException: Failed to start quarkus
        at io.quarkus.runner.ApplicationImpl.<clinit>(Unknown Source)
        ... 49 more
Caused by: javax.enterprise.inject.AmbiguousResolutionException: Beans: [CLASS bean [class=companyx.api.project.ProjectParams, id=9fbe6c147b4e4613d0947934fb37c85f9738382b], CLASS bean [class=companyx.api.storage.AssetParams, id=200da7b2e76e0435661fa5435234030fd029f6f6], CLASS bean [class=companyx.api.artifact.ArtifactParams, id=ccde4a7e2f9460f415624c81466a3936ac3253d7], CLASS bean [class=companyx.api.query.RowParams, id=fef36db73899ee70ae3eed9ab9975fc01852e211]]
        at io.quarkus.arc.impl.ArcContainerImpl.createInstanceSupplier(ArcContainerImpl.java:268)
        at io.quarkus.arc.impl.ArcContainerImpl.beanInstanceSupplier(ArcContainerImpl.java:240)
        at io.quarkus.arc.runtime.BeanContainerImpl.beanInstanceFactory(BeanContainerImpl.java:26)
        at io.quarkus.resteasy.reactive.common.runtime.ArcBeanFactory.<init>(ArcBeanFactory.java:15)
        at io.quarkus.resteasy.reactive.server.runtime.ResteasyReactiveRecorder$11.apply(ResteasyReactiveRecorder.java:311)
        at io.quarkus.resteasy.reactive.server.runtime.ResteasyReactiveRecorder$11.apply(ResteasyReactiveRecorder.java:308)
        at org.jboss.resteasy.reactive.server.core.startup.RuntimeResourceDeployment.parameterExtractor(RuntimeResourceDeployment.java:688)
        at org.jboss.resteasy.reactive.server.core.startup.RuntimeResourceDeployment.buildResourceMethod(RuntimeResourceDeployment.java:341)
        at org.jboss.resteasy.reactive.server.core.startup.RuntimeDeploymentManager.deploy(RuntimeDeploymentManager.java:118)
        at io.quarkus.resteasy.reactive.server.runtime.ResteasyReactiveRecorder.createDeployment(ResteasyReactiveRecorder.java:180)
        at io.quarkus.deployment.steps.ResteasyReactiveProcessor$setupDeployment208273900.deploy_1(Unknown Source)
        at io.quarkus.deployment.steps.ResteasyReactiveProcessor$setupDeployment208273900.deploy(Unknown Source)
        ... 50 more

Expected behavior

2.13 worked. These are generally pretty simple classes used for @BeanParams in both RESTful endpoints and the REST client.

Actual behavior

Fails to build and register REST endpoints and give ambiguous errors on classes used as @BeanParam.

Running build only

[ERROR] Caused by: javax.enterprise.inject.spi.DeploymentException: No annotations found on fields at 'companyx.api.feature.Feature'. Annotations like @QueryParam should be used in fields, not in methods.

Running with tests

Caused by: javax.enterprise.inject.AmbiguousResolutionException: Beans: [CLASS bean [class=companyx.api.project.ProjectParams, id=9fbe6c147b4e4613d0947934fb37c85f9738382b], CLASS bean [class=companyx.api.storage.AssetParams, id=200da7b2e76e0435661fa5435234030fd029f6f6], CLASS bean [class=companyx.api.artifact.ArtifactParams, id=ccde4a7e2f9460f415624c81466a3936ac3253d7], CLASS bean [class=companyx.api.query.RowParams, id=fef36db73899ee70ae3eed9ab9975fc01852e211]]

How to Reproduce?

For the life of me, I cannot seem to replicate this but I am trying.

Scenario 1 - Just build the codebase (multimodule project) without tests.

Scenario 2 - Run the tests.

Output of uname -a or ver

No response

Output of java -version

17.0.2

GraalVM version (if different from Java)

No response

Quarkus version or git rev

2.14.0.Final

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

Maven 3.8.4

Additional information

Similar to:

@kjq kjq added the kind/bug Something isn't working label Nov 12, 2022
@kjq kjq changed the title Upgrading to 2.14 breaks RESTClient and BeanParam Upgrading to 2.14 breaks REST resources (potentially because of BeanParam) Nov 12, 2022
@kjq
Copy link
Author

kjq commented Nov 12, 2022

What is interesting, is this is the first failure in a test that almost does nothing...

@Disabled
@QuarkusTest
@Tag("functional")
public class ArtifactParamTest {

    @Test
    void should_have_all_args() {
        ArtifactParams params = new ArtifactParams();
        params.setClient("a");
        params.setProject("b");
        params.setArtifact("c");
        assertNotNull(params.getClient());
        assertNotNull(params.getProject());
        assertNotNull(params.getArtifact());
    }

Giving this error:

Caused by: javax.enterprise.inject.AmbiguousResolutionException: Beans: [CLASS bean [class=companyx.api.artifact.ArtifactParams, id=ccde4a7e2f9460f415624c81466a3936ac3253d7], CLASS bean [class=companyx.api.storage.AssetParams, id=200da7b2e76e0435661fa5435234030fd029f6f6], CLASS bean [class=companyx.api.project.ProjectParams, id=9fbe6c147b4e4613d0947934fb37c85f9738382b], CLASS bean [class=companyx.api.query.RowParams, id=fef36db73899ee70ae3eed9ab9975fc01852e211]]

These are the classes:

@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class ArtifactParams extends ProjectParams {

    @PathParam("artifact")
    private String artifact;

    public ArtifactParams(final String artifact, final String project, final String client) {
        super(project, client);
        this.artifact = artifact;
    }
}
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class ProjectParams extends ClientParams {

    @PathParam("project")
    private String project;

    public ProjectParams(final String project, final String client) {
        super(client);
        this.project = project;
    }
}
@Data
public class AssetParams extends ProjectParams {
    
    @PathParam("filename")
    private String filename;

    @PathParam("ext")
    private String ext;
    
    @JsonIgnore
    public final String getFilename() {
        return filename + '.' + ext;
    }
}

@kjq
Copy link
Author

kjq commented Nov 12, 2022

I may of found one of the issues when "just building" - have @BeanParam somewhere was throwing everything into a tizzy (which might explain why I could not reproduce it with a simple scenario). Removing it everywhere allows me to get past this issue of ambiguous beans.

[ERROR] Caused by: javax.enterprise.inject.spi.DeploymentException: No annotations found on fields at 'companyx.api.feature.Feature'. Annotations like @QueryParam should be used in fields, not in methods.

For example: changing everywhere (basically remove @BeanParam completely) looks to work.

Uni<Client> locate(@BeanParam ClientParams params);

to this

Uni<Client> locate(ClientParams params);

I verified that is was @BeanParam "somewhere" by reverting and building (failed) then globally removing it and building (passed).

@kjq
Copy link
Author

kjq commented Nov 12, 2022

I decided to start over because I was getting lost in what I was testing. I still cannot reproduce it with a simple reproducer but I can verify that flip-flopping back and forth either resolve/brings back the issues...

  1. Created a new branch from 2.13 - works (just as a note we are doing everything reactively)
  2. Upgraded Quarkus to 2.14 / jandex / updated Stork (Configuration interface changed)
  3. mvn install - Fails with "ambiguous bean" on a simple test of just the class - literally just setting some properties on it (issue 2)
  4. Removed @BeanParam everywhere - no more "ambiguous bean" error
  5. mvn install - Fails with "javax.enterprise.inject.spi.DeploymentException: No annotations found on fields" (issue 1)

Here is where it get weird:

  1. Take a POJO used as an input to a REST method via a REST client interface and have that POJO either extend a xxxParams class or just have any bean param annotation (i.e. @QueryPath) - mvn install and everything works making me think it is specific to just this REST client and its usage.

In the REST client with @BeanParam removed (and this is implemented by a resource lower down)

Uni<Feature> save(final Feature feature, final ClientParams params);

I just picked the first place the errors happened and extends one of the Params or as I found out later added a dummy @QueryParam property...

@Data
@RegisterForReflection
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class Feature extends ClientParams{

I can verify that:

  • Having @BeanParam somewhere/anywhere is causing me issues
  • For whatever reason extending a Params class once or just adding any annotated param property and everything will work even though the same pattern is applied across the codebase and theoretically you would think I need to repeat it.

It may have something to do with (where I am at now):

  • This specific REST client / Resource - as it is the only one with a POST taking in a payload and params (all of our other REST clients are GET with only params).
  • I have other REST resources, having nothing to do with REST clients, that work fine (like public Uni<ProjectResponse> create(final ProjectRequest request, final ClientParams params)) with/without @BeanParam (i prefer it though to be explicit).

Summary of problems:

  • @BeanParam classes are being picked up as if they were CDI injected beans causing ambiguous reference errors when building - removing all occurrences of @BeanParam gets past this.
  • REST resources, that have nothing to do with REST clients, work as expected. Spot testing the @BeanParam or without it seems fine.
  • REST clients that take in a payload and params throws an exception about needing at least one param annotated field. Adding a dummy field (i.e. @QueryParam) to the payload class gets past the issue and everything will then work.
  • No matter how I try I cannot seem to replicate this in a small reproducer.

@kjq
Copy link
Author

kjq commented Nov 12, 2022

I cobbled the hec out of the projects to try and get you a reproducer. Hopefully this helps.

In all case, just running mvn install should be enough - the before/after are the exact same code...

Working as-is with 2.13.4
before.zip

Here is the "ambiguous" bean error and then after removing @BeanParam everywhere
issue-1.zip
resolve-1.zip

Hopefully this helps pinpoint the issue...

@quarkus-bot
Copy link

quarkus-bot bot commented Nov 13, 2022

/cc @FroMage, @geoand, @stuartwdouglas

@geoand
Copy link
Contributor

geoand commented Nov 14, 2022

@FroMage This looks like it could be due to the changes made to unify @BeanParam and multipart handling.
Can you take a look?

@FroMage
Copy link
Member

FroMage commented Nov 14, 2022

Sure.

@FroMage FroMage self-assigned this Nov 14, 2022
@geoand
Copy link
Contributor

geoand commented Nov 14, 2022

🙏🏼

@FroMage
Copy link
Member

FroMage commented Nov 14, 2022

I think this has to do with getters not being supported by bean params, but I'm pretty sure I didn't remove that, we talked about it: I think this was never implemented. So let's dig in.

@FroMage
Copy link
Member

FroMage commented Nov 14, 2022

Oh wait, this is client, not server.

@kjq
Copy link
Author

kjq commented Nov 14, 2022

If it adds to the conversation, I removed all occurrences of @BeanParam and got rid of POST/PUT methods specifically in the REST clients and was able to get it working (or at least I think it did - tests passed and REST smoke tests worked). For whatever reason it seems to throw the exceptions on those (# 1 above).

@FroMage
Copy link
Member

FroMage commented Nov 14, 2022

The ambiguous resolution is lying to us: it's not a client bug, but a server bug. The client is fine with it. It only happens in your reproducer because the server picks up some client interfaces and creates a deployment. Not sure why yet, because I can't reproduce it outside of your project yet.
But it's at least a real server bug. It happens because you have a bean param class extending another bean param class, and both are registered as CDI beans, and when we look up the parent class, it's ambiguous because it's provided by both the client and the subclass. That I can reproduce, so far, and will try to fix. We'll see about why the server creates a deployment, and what the runtime exception is later.

@kjq
Copy link
Author

kjq commented Nov 14, 2022

Hah, that makes me feel better. I tried creating a simple reproducer (all day) at first using my standard template and I could not reproduce it. The only I could replicate it was to take our entire project, gut it, and then try...

@kjq
Copy link
Author

kjq commented Nov 18, 2022

Curious if you have had any luck with this since we are putting together a plan to either hold-off or remove all use of @BeanParams because it is starting to cause us other issues downstream.

@FroMage
Copy link
Member

FroMage commented Nov 18, 2022

I'm still working on this, but I'm juggling other priorities as well.

@FroMage
Copy link
Member

FroMage commented Nov 18, 2022

I think I've a fix for the "ambiguous" error. But I don't quite know how to trigger the second from your source code, which is using Lombok and should just keep the annotations on the fields, even with the properties accessors generated

@FroMage
Copy link
Member

FroMage commented Nov 18, 2022

We don't support bean params with annotations on the accessors, but it doesn't seem to be your case.

@FroMage
Copy link
Member

FroMage commented Nov 18, 2022

Would you be willing to build Quarkus from sources with my fix to verify that it works for you?

@kjq
Copy link
Author

kjq commented Nov 18, 2022 via email

@FroMage
Copy link
Member

FroMage commented Nov 18, 2022

OK, so, can you try #29355 ? Thanks!

@kjq
Copy link
Author

kjq commented Nov 18, 2022 via email

@kjq
Copy link
Author

kjq commented Nov 18, 2022

Quick update, I finally got your fork/ref to compile (had to disable gradle for some reason), and I can match up your changes...

At a quick pass, it seems to compile with @BeanParams now and is failing very specifically on one @BeanParam usage. I am going to dig into it more.

Looks like progress though ;)

@kjq
Copy link
Author

kjq commented Nov 19, 2022

I think I found it, or at least the cause. Once we got past the ambiguous bean compilation error it seem to have nothing more to do with that.

What I realized was that only methods referencing a specific bean was causing the problems. Didn't matter if it came from a RESTClient, had a @BeanParam or not, just annotating it as a REST method, Lombok or not - they all failed.

The failure was the same in all cases and specific to the a single payload. If I took that payload out everything worked.

quarkus.builder.BuildException: Build failure: Build failed due to errors
[ERROR]         [error]: Build step io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#setupEndpoints threw an exception: java.lang.RuntimeException: java.lang.RuntimeException: Failed to process method 'companyx.api.extension.ExtensionClient#save'
[ERROR]         at org.jboss.resteasy.reactive.common.processor.EndpointIndexer.createEndpoints(EndpointIndexer.java:315)
[ERROR]         at io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor.setupEndpoints(ResteasyReactiveProcessor.java:613)
[ERROR]         at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[ERROR]         at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
[ERROR]         at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[ERROR]         at java.base/java.lang.reflect.Method.invoke(Method.java:568)
[ERROR]         at io.quarkus.deployment.ExtensionLoader$3.execute(ExtensionLoader.java:909)
[ERROR]         at io.quarkus.builder.BuildContext.run(BuildContext.java:281)
[ERROR]         at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
[ERROR]         at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
[ERROR]         at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
[ERROR]         at java.base/java.lang.Thread.run(Thread.java:833)
[ERROR]         at org.jboss.threads.JBossThread.run(JBossThread.java:501)
[ERROR] Caused by: java.lang.RuntimeException: Failed to process method 'companyx.api.extension.ExtensionClient#save'
[ERROR]         at org.jboss.resteasy.reactive.common.processor.EndpointIndexer.createResourceMethod(EndpointIndexer.java:754)
[ERROR]         at org.jboss.resteasy.reactive.common.processor.EndpointIndexer.createEndpoints(EndpointIndexer.java:404)
[ERROR]         at org.jboss.resteasy.reactive.common.processor.EndpointIndexer.createEndpoints(EndpointIndexer.java:286)
[ERROR]         ... 12 more
[ERROR] Caused by: javax.enterprise.inject.spi.DeploymentException: No annotations found on fields at 'companyx.api.extension.Extension'. Annotations like `@QueryParam` should be used in fields, not in methods.
[ERROR]         at org.jboss.resteasy.reactive.server.processor.ServerEndpointIndexer.handleBeanParam(ServerEndpointIndexer.java:185)
[ERROR]         at org.jboss.resteasy.reactive.common.processor.EndpointIndexer.createResourceMethod(EndpointIndexer.java:612)
[ERROR]         ... 14 more
[ERROR] -> [Help 1]

So, I took that specific bean apart piece by piece until I could reproduce the error again...ithe error occurs when it hits this annotation @DefaultValue("created"). If I take it out it works fine.

@Schema(hidden = true)
@DefaultValue("CREATED")
private ExtensionStatus status = ExtensionStatus.CREATED;

I believe the reason is that by using @DefaultValue we trigger the @BeanParam (per the javadocs of the annotation) even though it is not a BeanParam! That is why the error about "nothing being annotated for @BeanParam" gets thrown because it thought that payload was a BeanParam and there were not normal BeanParam (PathParam, QueryParam, etc.) annotated fields.

This is also why we could not reproduce it (or if we did it was by mistake and not obvious). Never thought about having all the annotated fields in there...

So, you fixed the ambiguous BeanParam. This issue was a mis-used annotation that is meant for BeanParams but was used in a bean that is not one.

I think this will close this ticket out once your changes are merged in! Thanks for all your help.

@FroMage
Copy link
Member

FroMage commented Nov 21, 2022

Ah, OK, so that explains the second issue that I could not reproduce. Good work hunting it down! I didn't expect @DefaultValue to trigger it, I thought it was limited to @Rest* and @*Param. Thanks a lot!

FroMage added a commit to FroMage/quarkus that referenced this issue Nov 21, 2022
FroMage added a commit to FroMage/quarkus that referenced this issue Nov 22, 2022
FroMage added a commit to FroMage/quarkus that referenced this issue Nov 22, 2022
@quarkus-bot quarkus-bot bot added this to the 2.15 - main milestone Nov 24, 2022
@gsmet gsmet modified the milestones: 2.15 - main, 2.14.2.Final Nov 24, 2022
gsmet pushed a commit to gsmet/quarkus that referenced this issue Nov 24, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/rest kind/bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants