Repository: quarkusio/quarkus
Issue: RESTEasy Reactive and Kotlin coroutines throws "No RESTEasy Reactive request in progress"

### Describe the bug

When implementing a RESTEasy Reactive endpoint using Kotlin coroutines any attempt to access the current request throws IllegalStateException("No RESTEasy Reactive request in progress"). For example, any attempt at retrieving headers from an injected JAX-RS `HttpHeaders` interface throws the exception.

### Expected behavior

You are able to implement RESTEasy Reactive methods using Kotlin coroutines. That they work as expected and are able to access full range of API objects.

### Actual behavior

An IllegalStateException with "No RESTEasy Reactive request in progress" message is thrown.

### How to Reproduce?

[code-with-quarkus.zip](https://github.com/quarkusio/quarkus/files/7504012/code-with-quarkus.zip)


### Output of `uname -a` or `ver`

Darwin ... 21.1.0 Darwin Kernel Version 21.1.0: Wed Oct 13 17:33:24 PDT 2021; root:xnu-8019.41.5~1/RELEASE_ARM64_T8101 arm64

### Output of `java -version`

java version "17" 2021-09-14 LTS Java(TM) SE Runtime Environment (build 17+35-LTS-2724) Java HotSpot(TM) 64-Bit Server VM (build 17+35-LTS-2724, mixed mode, sharing)

### GraalVM version (if different from Java)

_No response_

### Quarkus version or git rev

`2.4.1` and current HEAD of `main`

### Build tool (ie. output of `mvnw --version` or `gradlew --version`)

Apache Maven 3.8.1 (05c21c65bdfed0f71a2f2ada8b84da59348c4c5d) Maven home: /Users/kdubb/.m2/wrapper/dists/apache-maven-3.8.1-bin/2l5mhf2pq2clrde7f7qp1rdt5m/apache-maven-3.8.1 Java version: 17, vendor: Oracle Corporation, runtime: /Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home Default locale: en_US, platform encoding: UTF-8 OS name: "mac os x", version: "12.0.1", arch: "aarch64", family: "mac"

### Additional information

_No response_

Changed files:
extensions/resteasy-reactive/quarkus-resteasy-reactive-kotlin/runtime/src/main/kotlin/org/jboss/resteasy/reactive/server/runtime/kotlin/ApplicationCoroutineScope.kt
extensions/resteasy-reactive/quarkus-resteasy-reactive-kotlin/runtime/src/main/kotlin/org/jboss/resteasy/reactive/server/runtime/kotlin/FilterUtils.kt
extensions/resteasy-reactive/quarkus-resteasy-reactive-kotlin/runtime/src/main/kotlin/org/jboss/resteasy/reactive/server/runtime/kotlin/CoroutineInvocationHandler.kt
extensions/resteasy-reactive/quarkus-resteasy-reactive-kotlin/runtime/src/main/kotlin/org/jboss/resteasy/reactive/server/runtime/kotlin/FlowToPublisherHandler.kt
integration-tests/resteasy-reactive-kotlin/standard/src/main/kotlin/io/quarkus/it/resteasy/reactive/kotlin/GreetingResource.kt

diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive-kotlin/runtime/src/main/kotlin/org/jboss/resteasy/reactive/server/runtime/kotlin/ApplicationCoroutineScope.kt b/extensions/resteasy-reactive/quarkus-resteasy-reactive-kotlin/runtime/src/main/kotlin/org/jboss/resteasy/reactive/server/runtime/kotlin/ApplicationCoroutineScope.kt
index ff07849ae1c..036947f3b43 100644
--- a/extensions/resteasy-reactive/quarkus-resteasy-reactive-kotlin/runtime/src/main/kotlin/org/jboss/resteasy/reactive/server/runtime/kotlin/ApplicationCoroutineScope.kt
+++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive-kotlin/runtime/src/main/kotlin/org/jboss/resteasy/reactive/server/runtime/kotlin/ApplicationCoroutineScope.kt
@@ -2,6 +2,8 @@ package org.jboss.resteasy.reactive.server.runtime.kotlin
 
 import io.vertx.core.Context
 import kotlinx.coroutines.*
+import org.jboss.resteasy.reactive.server.core.CurrentRequestManager
+import org.jboss.resteasy.reactive.server.core.ResteasyReactiveRequestContext
 import org.jboss.resteasy.reactive.spi.ThreadSetupAction
 import javax.annotation.PreDestroy
 import javax.inject.Singleton
@@ -27,14 +29,16 @@ class ApplicationCoroutineScope : CoroutineScope, AutoCloseable {
 /**
  * Dispatches the coroutine in Vertx IO thread.
  */
-class VertxDispatcher(private val vertxContext: Context, private val requestScope : ThreadSetupAction.ThreadState) : CoroutineDispatcher() {
+class VertxDispatcher(private val vertxContext: Context, private val requestScope : ThreadSetupAction.ThreadState, private val rrContext: ResteasyReactiveRequestContext) : CoroutineDispatcher() {
     override fun dispatch(context: CoroutineContext, block: Runnable) {
         // context propagation for suspending functions is not enabled yet, will be handled later
         vertxContext.runOnContext {
             requestScope.activate()
+            CurrentRequestManager.set(rrContext);
             try {
                 block.run()
             } finally {
+                CurrentRequestManager.set(null);
                 requestScope.deactivate()
             }
         }
diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive-kotlin/runtime/src/main/kotlin/org/jboss/resteasy/reactive/server/runtime/kotlin/CoroutineInvocationHandler.kt b/extensions/resteasy-reactive/quarkus-resteasy-reactive-kotlin/runtime/src/main/kotlin/org/jboss/resteasy/reactive/server/runtime/kotlin/CoroutineInvocationHandler.kt
index 4cf40d8098d..97426b6a1ce 100644
--- a/extensions/resteasy-reactive/quarkus-resteasy-reactive-kotlin/runtime/src/main/kotlin/org/jboss/resteasy/reactive/server/runtime/kotlin/CoroutineInvocationHandler.kt
+++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive-kotlin/runtime/src/main/kotlin/org/jboss/resteasy/reactive/server/runtime/kotlin/CoroutineInvocationHandler.kt
@@ -27,7 +27,7 @@ class CoroutineInvocationHandler(private val invoker: EndpointInvoker,
         }
 
         val requestScope = requestContext.captureCDIRequestScope()
-        val dispatcher: CoroutineDispatcher = Vertx.currentContext()?.let {VertxDispatcher(it,requestScope)}
+        val dispatcher: CoroutineDispatcher = Vertx.currentContext()?.let {VertxDispatcher(it,requestScope, requestContext)}
                 ?: throw IllegalStateException("No Vertx context found")
 
         logger.trace("Handling request with dispatcher {}", dispatcher)
diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive-kotlin/runtime/src/main/kotlin/org/jboss/resteasy/reactive/server/runtime/kotlin/FilterUtils.kt b/extensions/resteasy-reactive/quarkus-resteasy-reactive-kotlin/runtime/src/main/kotlin/org/jboss/resteasy/reactive/server/runtime/kotlin/FilterUtils.kt
index 8ebd7e75820..07d8fe72e1d 100644
--- a/extensions/resteasy-reactive/quarkus-resteasy-reactive-kotlin/runtime/src/main/kotlin/org/jboss/resteasy/reactive/server/runtime/kotlin/FilterUtils.kt
+++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive-kotlin/runtime/src/main/kotlin/org/jboss/resteasy/reactive/server/runtime/kotlin/FilterUtils.kt
@@ -7,7 +7,7 @@ import javax.enterprise.inject.spi.CDI
 
 fun prepareExecution(requestContext: ResteasyReactiveRequestContext): Pair<CoroutineDispatcher, ApplicationCoroutineScope> {
     val requestScope = requestContext.captureCDIRequestScope()
-    val dispatcher: CoroutineDispatcher = Vertx.currentContext()?.let {VertxDispatcher(it,requestScope)}
+    val dispatcher: CoroutineDispatcher = Vertx.currentContext()?.let {VertxDispatcher(it,requestScope, requestContext)}
             ?: throw IllegalStateException("No Vertx context found")
 
     val coroutineScope = CDI.current().select(ApplicationCoroutineScope::class.java)
diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive-kotlin/runtime/src/main/kotlin/org/jboss/resteasy/reactive/server/runtime/kotlin/FlowToPublisherHandler.kt b/extensions/resteasy-reactive/quarkus-resteasy-reactive-kotlin/runtime/src/main/kotlin/org/jboss/resteasy/reactive/server/runtime/kotlin/FlowToPublisherHandler.kt
index 6d32cb6e939..0dee691bac3 100644
--- a/extensions/resteasy-reactive/quarkus-resteasy-reactive-kotlin/runtime/src/main/kotlin/org/jboss/resteasy/reactive/server/runtime/kotlin/FlowToPublisherHandler.kt
+++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive-kotlin/runtime/src/main/kotlin/org/jboss/resteasy/reactive/server/runtime/kotlin/FlowToPublisherHandler.kt
@@ -19,7 +19,7 @@ class FlowToPublisherHandler : ServerRestHandler {
         if (result is Flow<*>) {
 
             val requestScope = requestContext.captureCDIRequestScope()
-            val dispatcher: CoroutineDispatcher = Vertx.currentContext()?.let {VertxDispatcher(it,requestScope)}
+            val dispatcher: CoroutineDispatcher = Vertx.currentContext()?.let {VertxDispatcher(it,requestScope, requestContext)}
                     ?: throw IllegalStateException("No Vertx context found")
 
             val coroutineScope = CDI.current().select(ApplicationCoroutineScope::class.java)
diff --git a/integration-tests/resteasy-reactive-kotlin/standard/src/main/kotlin/io/quarkus/it/resteasy/reactive/kotlin/GreetingResource.kt b/integration-tests/resteasy-reactive-kotlin/standard/src/main/kotlin/io/quarkus/it/resteasy/reactive/kotlin/GreetingResource.kt
index cb3e6529c0d..b4ceaaa4fcb 100644
--- a/integration-tests/resteasy-reactive-kotlin/standard/src/main/kotlin/io/quarkus/it/resteasy/reactive/kotlin/GreetingResource.kt
+++ b/integration-tests/resteasy-reactive-kotlin/standard/src/main/kotlin/io/quarkus/it/resteasy/reactive/kotlin/GreetingResource.kt
@@ -1,14 +1,19 @@
 package io.quarkus.it.resteasy.reactive.kotlin
 
 import org.jboss.resteasy.reactive.RestHeader
+import javax.inject.Inject
 import javax.ws.rs.GET
 import javax.ws.rs.Path
+import javax.ws.rs.core.HttpHeaders
 
 @Path("/greeting")
-class GreetingResource {
+class GreetingResource(val headers: HttpHeaders) {
 
     @GET
-    suspend fun testSuspend(@RestHeader("firstName") firstName: String, @RestHeader("lastName") lastName: String) = Greeting("hello $firstName $lastName")
+    suspend fun testSuspend(@RestHeader("firstName") firstName: String): Greeting {
+        val lastName = headers.getHeaderString("lastName");
+        return Greeting("hello $firstName $lastName")
+    }
 }
 
 data class Greeting(val message:String)