Repository: quarkusio/quarkus
Issue: Reactive REST Client breaks Hibernate Reactive Transactions

### Describe the bug

When combining the Reactive REST client with Hibernate Reactive, the Reactive REST client seems to break Context Propagation, leading to Hibernate Transactions not working as intended.

### Expected behavior

Using Reactive REST Client does not have any negative effects on Hibernate Reactive

### Actual behavior

Using Reactive REST Client will break Hibernate Reactive Transactions because a call to `sessionFactory.withSession()` within an existing transaction will result in a new session being created instead of re-using the previously existing session residing in context.

### How to Reproduce?

Reproducer: https://github.com/markusdlugi/hibernate-reactive-with-transaction (don't get confused by the naming)

Steps to reproduce the behavior:
1. Run the application
2. Open `http://localhost:8080/test`. It will fail with `java.lang.IllegalStateException: Couldn't find author 1`
3. Remove the REST call (`TestResource` line 48). If you repeat the test, it will now work, you get an author and some books.
4. Revert your change and add the REST call again. The test will fail again.
5. Remove the Hibernate Transaction by replacing `.withTransaction((session, tx)` in line 43 with `.withSession(session`. The test will now work again, even though the REST call is still in place.

It seems like after the REST call, the `session2` in the reproducer is not the same session as `session1` where the entity was initially persisted. This leads to the error. Seems like the Reactive REST client messes up the context propagation.

Not sure why the example works when getting rid of the transaction entirely, though.

### Output of `uname -a` or `ver`

Microsoft Windows [Version 10.0.18363.1556]

### Output of `java -version`

OpenJDK 64-Bit Server VM Corretto-11.0.10.9.1 (build 11.0.10+9-LTS, mixed mode)

### GraalVM version (if different from Java)

N/A

### Quarkus version or git rev

2.0.3.Final

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

Apache Maven 3.6.3

### Additional information

Possibly related to #16949? But this one seems more severe because you cannot mix Hibernate Reactive Transactions and the REST client at all.

Changed files:
extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/provider/ProviderPriorityTest.java
extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/HelloClient2.java
independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/RestClientRequestContext.java
extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/provider/ProviderTest.java
extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/TestBean.java
extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/provider/ProviderDisabledAutodiscoveryTest.java
extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/BasicRestClientTest.java
extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/HelloResource.java

diff --git a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/BasicRestClientTest.java b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/BasicRestClientTest.java
index 3e332a87d60..0256fd40771 100644
--- a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/BasicRestClientTest.java
+++ b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/BasicRestClientTest.java
@@ -45,4 +45,9 @@ void shouldHaveApplicationScopeByDefault() {
         Bean<?> resolvedBean = beanManager.resolve(beans);
         assertThat(resolvedBean.getScope()).isEqualTo(ApplicationScoped.class);
     }
+
+    @Test
+    void shouldInvokeClientResponseOnSameContext() {
+        assertThat(testBean.bug18977()).isEqualTo("Hello");
+    }
 }
diff --git a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/HelloClient2.java b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/HelloClient2.java
index ab81bc507fb..660c55a0260 100644
--- a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/HelloClient2.java
+++ b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/HelloClient2.java
@@ -1,16 +1,26 @@
 package io.quarkus.rest.client.reactive;
 
 import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.core.MediaType;
 
 import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
 
+import io.smallrye.mutiny.Uni;
+
 @RegisterRestClient(configKey = "hello2")
 public interface HelloClient2 {
     @POST
     @Consumes(MediaType.TEXT_PLAIN)
     @Path("/")
     String echo(String name);
+
+    @GET
+    String bug18977();
+
+    @GET
+    @Path("delay")
+    Uni<String> delay();
 }
diff --git a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/HelloResource.java b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/HelloResource.java
index 938d18738d1..5b18bc9564f 100644
--- a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/HelloResource.java
+++ b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/HelloResource.java
@@ -1,6 +1,9 @@
 package io.quarkus.rest.client.reactive;
 
+import java.time.Duration;
+
 import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
@@ -8,6 +11,11 @@
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Request;
 
+import org.eclipse.microprofile.rest.client.inject.RestClient;
+import org.junit.jupiter.api.Assertions;
+
+import io.smallrye.mutiny.Uni;
+
 @Path("/hello")
 @Produces(MediaType.TEXT_PLAIN)
 @Consumes(MediaType.TEXT_PLAIN)
@@ -16,4 +24,24 @@ public class HelloResource {
     public String echo(String name, @Context Request request) {
         return "hello, " + name;
     }
+
+    @RestClient
+    HelloClient2 client2;
+
+    @GET
+    public Uni<String> something() {
+        Thread thread = Thread.currentThread();
+        return client2.delay()
+                .map(foo -> {
+                    Assertions.assertSame(thread, Thread.currentThread());
+                    return foo;
+                });
+    }
+
+    @Path("delay")
+    @GET
+    public Uni<String> delay() {
+        return Uni.createFrom().item("Hello")
+                .onItem().delayIt().by(Duration.ofMillis(500));
+    }
 }
diff --git a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/TestBean.java b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/TestBean.java
index 06fd623c7da..8d7eade3b2f 100644
--- a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/TestBean.java
+++ b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/TestBean.java
@@ -27,4 +27,8 @@ String helloViaBuiltClient(String name) {
                 .build(HelloClient.class);
         return helloClient.echo(name);
     }
+
+    String bug18977() {
+        return client2.bug18977();
+    }
 }
diff --git a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/provider/ProviderDisabledAutodiscoveryTest.java b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/provider/ProviderDisabledAutodiscoveryTest.java
index b318c03b039..97922399e96 100644
--- a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/provider/ProviderDisabledAutodiscoveryTest.java
+++ b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/provider/ProviderDisabledAutodiscoveryTest.java
@@ -15,6 +15,7 @@
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
+import io.quarkus.rest.client.reactive.HelloClient2;
 import io.quarkus.rest.client.reactive.HelloResource;
 import io.quarkus.test.QuarkusUnitTest;
 import io.quarkus.test.common.http.TestHTTPResource;
@@ -24,9 +25,11 @@ public class ProviderDisabledAutodiscoveryTest {
     @RegisterExtension
     static final QuarkusUnitTest config = new QuarkusUnitTest()
             .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
-                    .addClasses(HelloResource.class, HelloClient.class, GlobalRequestFilter.class, GlobalResponseFilter.class)
+                    .addClasses(HelloResource.class, HelloClient2.class, HelloClient.class, GlobalRequestFilter.class,
+                            GlobalResponseFilter.class)
                     .addAsResource(
                             new StringAsset(setUrlForClass(HelloClient.class)
+                                    + setUrlForClass(HelloClient2.class)
                                     + "quarkus.rest-client-reactive.provider-autodiscovery=false"),
                             "application.properties"));
 
diff --git a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/provider/ProviderPriorityTest.java b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/provider/ProviderPriorityTest.java
index 45e8178d2de..2bcb717b51a 100644
--- a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/provider/ProviderPriorityTest.java
+++ b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/provider/ProviderPriorityTest.java
@@ -13,6 +13,7 @@
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
+import io.quarkus.rest.client.reactive.HelloClient2;
 import io.quarkus.rest.client.reactive.HelloResource;
 import io.quarkus.test.QuarkusUnitTest;
 
@@ -23,12 +24,14 @@ public class ProviderPriorityTest {
             .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
                     .addClasses(HelloResource.class,
                             HelloClient.class,
+                            HelloClient2.class,
                             HelloClientWithFilter.class,
                             ResponseFilterLowestPrio.class,
                             GlobalResponseFilter.class,
                             GlobalResponseFilterLowPrio.class)
                     .addAsResource(
                             new StringAsset(setUrlForClass(HelloClient.class)
+                                    + setUrlForClass(HelloClient2.class)
                                     + setUrlForClass(HelloClientWithFilter.class)),
                             "application.properties"));
 
diff --git a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/provider/ProviderTest.java b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/provider/ProviderTest.java
index 897db05f57d..8470d770a40 100644
--- a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/provider/ProviderTest.java
+++ b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/provider/ProviderTest.java
@@ -16,6 +16,7 @@
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
+import io.quarkus.rest.client.reactive.HelloClient2;
 import io.quarkus.rest.client.reactive.HelloResource;
 import io.quarkus.test.QuarkusUnitTest;
 import io.quarkus.test.common.http.TestHTTPResource;
@@ -25,11 +26,12 @@ public class ProviderTest {
     @RegisterExtension
     static final QuarkusUnitTest config = new QuarkusUnitTest()
             .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
-                    .addClasses(HelloResource.class, HelloClient.class, GlobalRequestFilter.class,
+                    .addClasses(HelloResource.class, HelloClient2.class, HelloClient.class, GlobalRequestFilter.class,
                             GlobalResponseFilter.class, GlobalRequestFilterConstrainedToServer.class,
                             GlobalFeature.class)
                     .addAsResource(
-                            new StringAsset(setUrlForClass(HelloClient.class)),
+                            new StringAsset(setUrlForClass(HelloClient.class)
+                                    + setUrlForClass(HelloClient2.class)),
                             "application.properties"));
 
     @RestClient
diff --git a/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/RestClientRequestContext.java b/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/RestClientRequestContext.java
index 467166cdf2d..33733d240ea 100644
--- a/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/RestClientRequestContext.java
+++ b/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/RestClientRequestContext.java
@@ -1,5 +1,6 @@
 package org.jboss.resteasy.reactive.client.impl;
 
+import io.vertx.core.Context;
 import io.vertx.core.MultiMap;
 import io.vertx.core.buffer.Buffer;
 import io.vertx.core.http.HttpClient;
@@ -219,7 +220,14 @@ public HttpClientResponse getVertxClientResponse() {
     @Override
     protected Executor getEventLoop() {
         if (httpClientRequest == null) {
-            return restClient.getVertx().nettyEventLoopGroup().next();
+            // make sure we execute the client callbacks on the same context as the current thread
+            Context context = restClient.getVertx().getOrCreateContext();
+            return new Executor() {
+                @Override
+                public void execute(Runnable command) {
+                    context.runOnContext(v -> command.run());
+                }
+            };
         } else {
             return new Executor() {
                 @Override