Describe the bug
When upgrading from 3.21.3 to 3.23.3 we ran into an issue where previously working Kotlin REST client methods are reported as invalid by the server indexer; the methods are Kotlin suspend methods that use parameters with @NotBody to add headers to the request. After a deep dive debugging ResteasyReactiveProcessor and EndpointIndexer I discovered the issue was much deeper.. that recent changes have made any Kotlin suspend method, or method that returns Any in a REST client or is a REST resource method, causes all REST clients interfaces to be passed to the server's endpoint indexer. Seemingly by luck, this didn't cause any issues until a recent change in 3.23.0.
Details
The crux of the issue is that certain methods (that suspend or return Any) contribute java.lang.Object to the returnsBySubResources value here:
|
Map<DotName, Set<DotName>> returnsBySubResources = new HashMap<>(); |
Having Object in that list causes all checking below to believe that anything being queried is a sub-resource of something, and therefore gets included in the toScan list further down. I believe this started in PR #46464.
This was caused by Kotlin suspend methods in our projects (because all suspend methods return the value or the continuation... so Object). It seemed like a more general problem and I created a minimal reproducer, and confirmed, that if you just return Any from an endpoint it causes the same behavior. It might affect Java resource methods that return Object but I haven't confirmed that.
While the referenced code cause has been causing the server to scan all the REST clients and their methods, it wasn't an issue. First, if the REST client doesn't violate any rules for server methods, it's not causing noticeable problems. Additionally, if a REST client method did violate the rules, no external exceptions was raised because of this code in EndpointIndexer, that essentially ignores all RuntimeErrors produced by interfaces:
|
if (e instanceof DeploymentException) { |
I confirmed that all the way back to 3.21.4 a RuntimeException for the violating client methods were being thrown, caught, and ignored here.
So, exceptions were being thrown, and ignored, until PR #47513. That PR changes the RuntimeException thrown to a DeploymentException. This has the effect of having the exception handler in EndpointIndexer @ line 342 immediately rethrow the exception, rather than check if it's an interface and ignore it.
Expected behavior
Methods that don't validate as server endpoints, but are valid client methods, work as expected (and had previously).
Additionally, it seems that no client interfaces should be passed to the server's endpoint indexer. It's adding work that doesn't need to be done and it seems like it will continue to cause issues similar to the one being reported.
Actual behavior
No response
How to Reproduce?
I've attached a simple reproducer. It's a basic project generated from quarkus.io with REST and REST client. I made two changes to the generated project.
- Added a POST method to the generated
MyRemoteService that uses an @NotBody parameters, this gives us a valid REST client method that is not a valid REST resource method.
- I changed the
hello method in GreetingResource to be suspend.
Running ./gradlew build will generate the error thrown by the endpoint indexer.
Additionally, to prove that it was not just suspend methods, I changed the hello method to return Any (both are in the reproducer with one commented out). Changing the method and building again will report the same issue.
Changing the hello method to return String and not be a suspend method, will fix the build error reported.
More interestingly...
Leaving the hello method as a suspend method or returning Any and removing the @NotBody header: String parameter from the POST method will cease the build failure as well. Upon inspection you'll see that the endpoint indexer is still getting passed the MyRemotService but since only method is also a valid server method, no errors are reported.
code-with-quarkus.zip
Output of uname -a or ver
MacOS 15.5
Output of java -version
Java 21
Quarkus version or git rev
3.23.3 (affects 3.23.0 and server indexing of client methods happens back to 3.21.4)
Build tool (ie. output of mvnw --version or gradlew --version)
Gradle 8.13
Additional information
No response
Describe the bug
When upgrading from
3.21.3to3.23.3we ran into an issue where previously working Kotlin REST client methods are reported as invalid by the server indexer; the methods are Kotlin suspend methods that use parameters with@NotBodyto add headers to the request. After a deep dive debuggingResteasyReactiveProcessorandEndpointIndexerI discovered the issue was much deeper.. that recent changes have made any Kotlinsuspendmethod, or method that returnsAnyin a REST client or is a REST resource method, causes all REST clients interfaces to be passed to the server's endpoint indexer. Seemingly by luck, this didn't cause any issues until a recent change in3.23.0.Details
The crux of the issue is that certain methods (that
suspendor returnAny) contributejava.lang.Objectto thereturnsBySubResourcesvalue here:quarkus/extensions/resteasy-reactive/rest/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/ResteasyReactiveProcessor.java
Line 760 in 67b95e5
Having
Objectin that list causes all checking below to believe that anything being queried is a sub-resource of something, and therefore gets included in thetoScanlist further down. I believe this started in PR #46464.This was caused by Kotlin
suspendmethods in our projects (because all suspend methods return the value or the continuation... soObject). It seemed like a more general problem and I created a minimal reproducer, and confirmed, that if you just returnAnyfrom an endpoint it causes the same behavior. It might affect Java resource methods that returnObjectbut I haven't confirmed that.While the referenced code cause has been causing the server to scan all the REST clients and their methods, it wasn't an issue. First, if the REST client doesn't violate any rules for server methods, it's not causing noticeable problems. Additionally, if a REST client method did violate the rules, no external exceptions was raised because of this code in
EndpointIndexer, that essentially ignores allRuntimeErrors produced by interfaces:quarkus/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java
Line 342 in 67b95e5
I confirmed that all the way back to
3.21.4aRuntimeExceptionfor the violating client methods were being thrown, caught, and ignored here.So, exceptions were being thrown, and ignored, until PR #47513. That PR changes the
RuntimeExceptionthrown to aDeploymentException. This has the effect of having the exception handler inEndpointIndexer@ line 342 immediately rethrow the exception, rather than check if it's an interface and ignore it.Expected behavior
Methods that don't validate as server endpoints, but are valid client methods, work as expected (and had previously).
Additionally, it seems that no client interfaces should be passed to the server's endpoint indexer. It's adding work that doesn't need to be done and it seems like it will continue to cause issues similar to the one being reported.
Actual behavior
No response
How to Reproduce?
I've attached a simple reproducer. It's a basic project generated from quarkus.io with REST and REST client. I made two changes to the generated project.
MyRemoteServicethat uses an@NotBodyparameters, this gives us a valid REST client method that is not a valid REST resource method.hellomethod inGreetingResourceto besuspend.Running
./gradlew buildwill generate the error thrown by the endpoint indexer.Additionally, to prove that it was not just
suspendmethods, I changed thehellomethod to returnAny(both are in the reproducer with one commented out). Changing the method and building again will report the same issue.Changing the
hellomethod to returnStringand not be a suspend method, will fix the build error reported.More interestingly...
Leaving the
hellomethod as asuspendmethod or returningAnyand removing the@NotBody header: Stringparameter from thePOSTmethod will cease the build failure as well. Upon inspection you'll see that the endpoint indexer is still getting passed theMyRemotServicebut since only method is also a valid server method, no errors are reported.code-with-quarkus.zip
Output of
uname -aorverMacOS 15.5
Output of
java -versionJava 21
Quarkus version or git rev
3.23.3 (affects 3.23.0 and server indexing of client methods happens back to 3.21.4)
Build tool (ie. output of
mvnw --versionorgradlew --version)Gradle 8.13
Additional information
No response