quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.75k stars 2.67k forks source link

Quarkus REST: AsyncInvoker doesn't fire callbacks #42610

Closed nicolasduminil closed 2 months ago

nicolasduminil commented 2 months ago

Describe the bug

I'm using Quarkus 3.11.0 with the quarkus-rest-client-jackson extension to asynchronously invoke a simple REST service. Using the polling feature seems to work as expected but using the callback one doesn't. The callback doesn't get called.

Expected behavior

Using statements like:

ClientBuilder.newClient().target(...).request().async().get(new TimeCallback());

I expect that the TimeCallback.completed() method be invoked when the result of the REST endpoint is available.

Actual behavior

The TimeCallback.completed() method isn't invoked.

How to Reproduce?

$ git clone https://github.com/nicolasduminil/quarkus-jaxrs-async-with-callback.git
$ cd quarkus-jaxrs-async-with-callback
$ mvn package
$ java -jar target/quarkus-app/quarkus-run.jar
...

In another terminal:

$ cd quarkus-jaxrs-async-with-callback
$ mvn -DtimeSrvUrl=http://localhost:8080/time failsafe:integration-test

The tests will run successfully despite the statement assertThat(false).isTrue(); in the TimeCallback.completed() method, proving that it doesn't get called. The output of the System.out.println(...) statements doesn't appear neither.

Output of uname -a or ver

Linux nicolas-XPS-13-9360 6.8.0-40-generic #40~22.04.3-Ubuntu SMP PREEMPT_DYNAMIC Tue Jul 30 17:30:19 UTC 2 x86_64 x86_64 x86_64 GNU/Linux

Output of java -version

java version "21.0.4" 2024-07-16 LTS Java(TM) SE Runtime Environment (build 21.0.4+8-LTS-274) Java HotSpot(TM) 64-Bit Server VM (build 21.0.4+8-LTS-274, mixed mode, sharing)

Quarkus version or git rev

3.11.0

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

Apache Maven 3.9.4 (dfbb324ad4a7c8fb0bf182e6d91b0ae20e3d2dd9) Maven home: /opt/apache-maven-3.9.4 Java version: 21.0.4, vendor: Oracle Corporation, runtime: /usr/lib/jvm/jdk-21.0.4-oracle-x64 Default locale: en_US, platform encoding: UTF-8 OS name: "linux", version: "6.8.0-40-generic", arch: "amd64", family: "unix"

Additional information

None

quarkus-bot[bot] commented 2 months ago

/cc @cescoffier (rest-client), @geoand (rest-client)

geoand commented 2 months ago

The problem is that when you do:

client.target(timeSrvUrl).request().async().get(new TimeCallback());

you are not waiting for the Future to complete. That results in the test finishing and ultimately the client being closed before the callback can be invoked.

Simply changing your code to something like:

client.target(timeSrvUrl).request().async().get(new TimeCallback()).get(10_000, TimeUnit.MILLISECONDS);

makes things work as expected.

nicolasduminil commented 2 months ago

I committed the mentioned correction into the project but testing it doesn't change anything. No exception is raised, showing that the statement assertThat(false).isTrue(); in TimeCallback.completed() isn't executed. And the only reason I see for it not being executed is that the callback isn't called.

Could you please confirm having tested it successfully ?

Thanks.

geoand commented 2 months ago

I'll take another look tomorrow, but I tried what I mentioned above and it worked as expected

nicolasduminil commented 2 months ago

Could you please just test the reproducer I provided and confirm it works in your environment ?

geoand commented 2 months ago

I tried your updated version and the completed method of the TimeCallback is invoked.

nicolasduminil commented 2 months ago

This is surprising as it still doesn't work for me. I mean, TimeCallback.completed() is invoked 'cause the message ### TimeCallback.completed: enter is displayed. But then the execution goes I don't know where as neither the statement assertThat(false).isTrue() doesn't raise exception nor the message ### TimeCallback.completed: exit is displayed.

So, it finished before the end. Any idea why and how to prevent that ? I thought that the effect of get(10, TimeUnit.SECONDS) at the line 44 was to prevent that.

I'm showing below the execution listing:

$ mvn -DtimeSrvUrl=http://localhost:8080/time failsafe:integration-test
[INFO] Scanning for projects...
[INFO] 
[INFO] ---< fr.simplex-software.workshop:quarkus-jaxrs-async-with-callback >---
[INFO] Building quarkus-jaxrs-async-with-callback 1.0-SNAPSHOT
[INFO]   from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- failsafe:3.2.5:integration-test (default-cli) @ quarkus-jaxrs-async-with-callback ---
[INFO] Using auto detected provider org.apache.maven.surefire.junitplatform.JUnitPlatformProvider
[INFO] 
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running fr.simplex_software.quarkus_simple.tests.TimeResourceIT
2024-08-29 16:59:44,034 INFO  [io.quarkus] (main) quarkus-jaxrs-async-with-callback 1.0-SNAPSHOT on JVM (powered by Quarkus 3.11.0) started in 1.816s. Listening on: http://localhost:8081
2024-08-29 16:59:44,036 INFO  [io.quarkus] (main) Profile test activated. 
2024-08-29 16:59:44,036 INFO  [io.quarkus] (main) Installed features: [cdi, rest, rest-client, rest-client-jackson, rest-jackson, smallrye-context-propagation, vertx]
### TimeCallback.completed: enter
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 3.891 s -- in fr.simplex_software.quarkus_simple.tests.TimeResourceIT
2024-08-29 16:59:44,285 INFO  [io.quarkus] (main) quarkus-jaxrs-async-with-callback stopped in 0.014s
[INFO] 
[INFO] Results:
[INFO] 
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  5.773 s
[INFO] Finished at: 2024-08-29T16:59:44+02:00
[INFO] ------------------------------------------------------------------------