Repository: quarkusio/quarkus
Issue: Error with RoutingContext Inject with Reactive routing

**Describe the bug**
If I inject RoutingContext in a RequestScoped bean, an error are throwed when I try to get him. The problem is identified with reactive route (normal ou blocking handler). With Jax RS service, it's OK.

**Expected behavior**
Access RoutingContext bean inject in RequestScoped bean.

**Actual behavior**
```
Reported exception:
SLF4J: Failed toString() invocation on an object of type [io.quarkus.RequestScopedService_ClientProxy]
Reported exception:
javax.enterprise.inject.IllegalProductException: Normal scoped producer method may not return null: io.quarkus.vertx.http.runtime.CurrentVertxRequest.getCurrent()
	at io.quarkus.vertx.http.runtime.CurrentVertxRequest_ProducerMethod_getCurrent_6dc23d16d53ba5c34e1e7b6f54290fd7b9aebd76_Bean.create(CurrentVertxRequest_ProducerMethod_getCurrent_6dc23d16d53ba5c34e1e7b6f54290fd7b9aebd76_Bean.zig:178)
	at io.quarkus.vertx.http.runtime.CurrentVertxRequest_ProducerMethod_getCurrent_6dc23d16d53ba5c34e1e7b6f54290fd7b9aebd76_Bean.create(CurrentVertxRequest_ProducerMethod_getCurrent_6dc23d16d53ba5c34e1e7b6f54290fd7b9aebd76_Bean.zig:197)
	at io.quarkus.arc.impl.RequestContext.get(RequestContext.java:67)
	at io.quarkus.vertx.http.runtime.CurrentVertxRequest_ProducerMethod_getCurrent_6dc23d16d53ba5c34e1e7b6f54290fd7b9aebd76_ClientProxy.arc$delegate(CurrentVertxRequest_ProducerMethod_getCurrent_6dc23d16d53ba5c34e1e7b6f54290fd7b9aebd76_ClientProxy.zig:100)
	at io.quarkus.vertx.http.runtime.CurrentVertxRequest_ProducerMethod_getCurrent_6dc23d16d53ba5c34e1e7b6f54290fd7b9aebd76_ClientProxy.toString(CurrentVertxRequest_ProducerMethod_getCurrent_6dc23d16d53ba5c34e1e7b6f54290fd7b9aebd76_ClientProxy.zig:942)
	at java.base/java.lang.String.valueOf(String.java:2951)
	at io.quarkus.RequestScopedService.toString(RequestScopedService.java:20)
	at io.quarkus.RequestScopedService_ClientProxy.toString(RequestScopedService_ClientProxy.zig:161)
	at org.slf4j.helpers.MessageFormatter.safeObjectAppend(MessageFormatter.java:277)
	at org.slf4j.helpers.MessageFormatter.deeplyAppendParameter(MessageFormatter.java:249)
	at org.slf4j.helpers.MessageFormatter.arrayFormat(MessageFormatter.java:211)
	at org.slf4j.helpers.MessageFormatter.arrayFormat(MessageFormatter.java:161)
	at org.slf4j.helpers.MessageFormatter.format(MessageFormatter.java:124)
	at org.jboss.slf4j.JBossLoggerAdapter.info(JBossLoggerAdapter.java:183)
	at io.quarkus.TestRoute.test(TestRoute.java:21)
	at io.quarkus.TestRoute_RouteHandler_test_996e1735fd0007ce67bd96d669ec34af05f4f2db.invoke(TestRoute_RouteHandler_test_996e1735fd0007ce67bd96d669ec34af05f4f2db.zig:109)
	at io.quarkus.vertx.web.runtime.RouteHandler.handle(RouteHandler.java:53)
	at io.quarkus.vertx.web.runtime.RouteHandler.handle(RouteHandler.java:17)
	at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1036)
	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:95)
	at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:132)
	at io.quarkus.vertx.http.runtime.VertxHttpRecorder$16.handle(VertxHttpRecorder.java:1080)
	at io.quarkus.vertx.http.runtime.VertxHttpRecorder$16.handle(VertxHttpRecorder.java:1051)
	at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1036)
	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:131)
	at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:132)
	at io.quarkus.vertx.http.runtime.VertxHttpRecorder$4.handle(VertxHttpRecorder.java:306)
	at io.quarkus.vertx.http.runtime.VertxHttpRecorder$4.handle(VertxHttpRecorder.java:284)
	at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1036)
	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:131)
	at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:132)
	at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$3.handle(VertxHttpHotReplacementSetup.java:85)
	at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$3.handle(VertxHttpHotReplacementSetup.java:74)
	at io.vertx.core.impl.ContextImpl.lambda$null$0(ContextImpl.java:327)
	at io.vertx.core.impl.ContextImpl.executeTask(ContextImpl.java:366)
	at io.vertx.core.impl.EventLoopContext.lambda$executeAsync$0(EventLoopContext.java:38)
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:834)
```


**To Reproduce**

With the attach project

```
$ curl localhost:8080/reactive/ 
javax.enterprise.inject.IllegalProductException: Normal scoped producer method may not return null: io.quarkus.vertx.http.runtime.CurrentVertxRequest.getCurrent()
	at io.quarkus.vertx.http.runtime.CurrentVertxRequest_ProducerMethod_getCurrent_6dc23d16d53ba5c34e1e7b6f54290fd7b9aebd76_Bean.create(CurrentVertxRequest_ProducerMethod_getCurrent_6dc23d16d53ba5c34e1e7b6f54290fd7b9aebd76_Bean.zig:178)
	...
[bug-inject-routing-context.tar.gz](https://github.com/quarkusio/quarkus/files/5532303/bug-inject-routing-context.tar.gz)
[bug-inject-routing-context.tar.gz](https://github.com/quarkusio/quarkus/files/5532306/bug-inject-routing-context.tar.gz)


2020-11-12 18:45:46,881 INFO  [io.qua.TestRoute] (vert.x-eventloop-thread-16) RequestScopedService: [FAILED toString()]

$ curl localhost:8080/jaxrs/ 
2020-11-12 18:46:31,058 INFO  [io.qua.TestResource] (executor-thread-1) RequestScopedService: RequestScopedService{routingContext=io.vertx.ext.web.impl.RoutingContextImpl@4c88e5f5}

```
[bug-inject-routing-context.tar.gz](https://github.com/quarkusio/quarkus/files/5532316/bug-inject-routing-context.tar.gz)


Changed files:
extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/Methods.java
extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/VertxWebProcessor.java
extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/runtime/VertxWebRecorder.java
extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/runtime/RouteHandler.java
extensions/vertx-web/deployment/src/test/java/io/quarkus/vertx/web/SimpleRouteTest.java
extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/runtime/RouteHandlers.java

diff --git a/extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/Methods.java b/extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/Methods.java
index c9e2fe6b6f8..425efffb2cf 100644
--- a/extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/Methods.java
+++ b/extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/Methods.java
@@ -27,6 +27,7 @@
 import io.quarkus.vertx.web.runtime.MultiJsonArraySupport;
 import io.quarkus.vertx.web.runtime.MultiSseSupport;
 import io.quarkus.vertx.web.runtime.MultiSupport;
+import io.quarkus.vertx.web.runtime.RouteHandler;
 import io.quarkus.vertx.web.runtime.RouteHandlers;
 import io.quarkus.vertx.web.runtime.ValidationSupport;
 import io.smallrye.mutiny.Multi;
@@ -169,7 +170,7 @@ class Methods {
             .ofMethod(InjectableBean.class, "destroy",
                     void.class, Object.class,
                     CreationalContext.class);
-    static final MethodDescriptor OBJECT_CONSTRUCTOR = MethodDescriptor.ofConstructor(Object.class);
+    static final MethodDescriptor ROUTE_HANDLER_CONSTRUCTOR = MethodDescriptor.ofConstructor(RouteHandler.class);
 
     static final MethodDescriptor ROUTE_HANDLERS_SET_CONTENT_TYPE = MethodDescriptor
             .ofMethod(RouteHandlers.class, "setContentType", void.class, RoutingContext.class, String.class);
diff --git a/extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/VertxWebProcessor.java b/extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/VertxWebProcessor.java
index e9f2d1991b5..4e7bae6d14a 100644
--- a/extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/VertxWebProcessor.java
+++ b/extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/VertxWebProcessor.java
@@ -388,8 +388,6 @@ void addAdditionalRoutes(
         }
 
         detectConflictingRoutes(matchers);
-
-        recorder.clearCacheOnShutdown(shutdown);
     }
 
     @BuildStep(onlyIf = IsDevelopment.class)
@@ -522,7 +520,7 @@ private String generateHandler(HandlerDescriptor desc, BeanInfo bean, MethodInfo
                 + HashUtil.sha1(sigBuilder.toString() + hashSuffix);
 
         ClassCreator invokerCreator = ClassCreator.builder().classOutput(classOutput).className(generatedName)
-                .interfaces(RouteHandler.class).build();
+                .superClass(RouteHandler.class).build();
 
         // Initialized state
         FieldCreator beanField = invokerCreator.getFieldCreator("bean", InjectableBean.class)
@@ -558,7 +556,7 @@ void implementConstructor(BeanInfo bean, ClassCreator invokerCreator, FieldCreat
             FieldCreator containerField, FieldCreator validatorField) {
         MethodCreator constructor = invokerCreator.getMethodCreator("<init>", void.class);
         // Invoke super()
-        constructor.invokeSpecialMethod(Methods.OBJECT_CONSTRUCTOR, constructor.getThis());
+        constructor.invokeSpecialMethod(Methods.ROUTE_HANDLER_CONSTRUCTOR, constructor.getThis());
 
         ResultHandle containerHandle = constructor
                 .invokeStaticMethod(Methods.ARC_CONTAINER);
diff --git a/extensions/vertx-web/deployment/src/test/java/io/quarkus/vertx/web/SimpleRouteTest.java b/extensions/vertx-web/deployment/src/test/java/io/quarkus/vertx/web/SimpleRouteTest.java
index c2d0ef263f2..d36d20beffd 100644
--- a/extensions/vertx-web/deployment/src/test/java/io/quarkus/vertx/web/SimpleRouteTest.java
+++ b/extensions/vertx-web/deployment/src/test/java/io/quarkus/vertx/web/SimpleRouteTest.java
@@ -54,6 +54,7 @@ public void testSimpleRoute() {
         given().contentType("text/plain").body("world")
                 .post("/body").then().body(is("Hello world!"));
         when().get("/request").then().statusCode(200).body(is("HellO!"));
+        when().get("/inject?foo=Hey").then().statusCode(200).body(is("Hey"));
     }
 
     @Test
@@ -108,6 +109,11 @@ void request(RoutingContext context) {
             context.response().setStatusCode(200).end(transformer.transform("Hello!"));
         }
 
+        @Route
+        void inject(RoutingExchange exchange) {
+            exchange.ok(transformer.getFoo());
+        }
+
     }
 
     static class SimpleRoutesBean {
@@ -157,10 +163,17 @@ String generate(String name) {
     @RequestScoped
     static class Transformer {
 
+        @Inject
+        RoutingContext context;
+
         String transform(String message) {
             return message.replace('o', 'O');
         }
 
+        String getFoo() {
+            return context.request().getParam("foo");
+        }
+
     }
 
 }
diff --git a/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/runtime/RouteHandler.java b/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/runtime/RouteHandler.java
index 024d5dd1475..f378da5ee0e 100644
--- a/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/runtime/RouteHandler.java
+++ b/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/runtime/RouteHandler.java
@@ -1,8 +1,12 @@
 package io.quarkus.vertx.web.runtime;
 
+import javax.enterprise.event.Event;
+
 import io.quarkus.arc.Arc;
 import io.quarkus.arc.InjectableContext;
 import io.quarkus.arc.ManagedContext;
+import io.quarkus.security.identity.SecurityIdentity;
+import io.quarkus.vertx.http.runtime.CurrentVertxRequest;
 import io.quarkus.vertx.http.runtime.security.QuarkusHttpUser;
 import io.quarkus.vertx.web.Route;
 import io.vertx.core.AsyncResult;
@@ -14,31 +18,40 @@
  * 
  * @see Route
  */
-public interface RouteHandler extends Handler<RoutingContext> {
+public abstract class RouteHandler implements Handler<RoutingContext> {
+
+    private final Event<SecurityIdentity> securityIdentityEvent;
+    private final CurrentVertxRequest currentVertxRequest;
+
+    public RouteHandler() {
+        this.securityIdentityEvent = Arc.container().beanManager().getEvent().select(SecurityIdentity.class);
+        this.currentVertxRequest = Arc.container().instance(CurrentVertxRequest.class).get();
+    }
 
     /**
      * Invokes the route method.
      * 
      * @param context
      */
-    void invoke(RoutingContext context);
+    public abstract void invoke(RoutingContext context);
 
     @Override
-    default void handle(RoutingContext context) {
+    public void handle(RoutingContext context) {
         QuarkusHttpUser user = (QuarkusHttpUser) context.user();
         ManagedContext requestContext = Arc.container().requestContext();
         //todo: how should we handle non-proactive authentication here?
         if (requestContext.isActive()) {
             if (user != null) {
-                RouteHandlers.fireSecurityIdentity(user.getSecurityIdentity());
+                securityIdentityEvent.fire(user.getSecurityIdentity());
             }
             invoke(context);
         } else {
             try {
                 // Activate the context, i.e. set the thread locals
                 requestContext.activate();
+                currentVertxRequest.setCurrent(context);
                 if (user != null) {
-                    RouteHandlers.fireSecurityIdentity(user.getSecurityIdentity());
+                    securityIdentityEvent.fire(user.getSecurityIdentity());
                 }
                 // Reactive routes can use async processing (e.g. mutiny Uni/Multi) and context propagation
                 // 1. Store the state (which is basically a shared Map instance)
diff --git a/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/runtime/RouteHandlers.java b/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/runtime/RouteHandlers.java
index 7bc476142e6..6303c0be1c7 100644
--- a/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/runtime/RouteHandlers.java
+++ b/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/runtime/RouteHandlers.java
@@ -1,10 +1,5 @@
 package io.quarkus.vertx.web.runtime;
 
-import javax.enterprise.event.Event;
-
-import io.quarkus.arc.Arc;
-import io.quarkus.arc.impl.LazyValue;
-import io.quarkus.security.identity.SecurityIdentity;
 import io.vertx.core.Handler;
 import io.vertx.core.http.HttpServerResponse;
 import io.vertx.ext.web.RoutingContext;
@@ -16,9 +11,6 @@ private RouteHandlers() {
 
     static final String CONTENT_TYPE = "content-type";
 
-    private static final LazyValue<Event<SecurityIdentity>> SECURITY_IDENTITY_EVENT = new LazyValue<>(
-            RouteHandlers::createEvent);
-
     public static void setContentType(RoutingContext context, String defaultContentType) {
         HttpServerResponse response = context.response();
         context.addHeadersEndHandler(new Handler<Void>() {
@@ -37,16 +29,4 @@ public void handle(Void aVoid) {
         });
     }
 
-    static void fireSecurityIdentity(SecurityIdentity identity) {
-        SECURITY_IDENTITY_EVENT.get().fire(identity);
-    }
-
-    static void clear() {
-        SECURITY_IDENTITY_EVENT.clear();
-    }
-
-    private static Event<SecurityIdentity> createEvent() {
-        return Arc.container().beanManager().getEvent().select(SecurityIdentity.class);
-    }
-
 }
diff --git a/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/runtime/VertxWebRecorder.java b/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/runtime/VertxWebRecorder.java
index 031b3b0eaf0..716a29b5a22 100644
--- a/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/runtime/VertxWebRecorder.java
+++ b/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/runtime/VertxWebRecorder.java
@@ -3,7 +3,6 @@
 import java.lang.reflect.InvocationTargetException;
 import java.util.function.Function;
 
-import io.quarkus.runtime.ShutdownContext;
 import io.quarkus.runtime.annotations.Recorder;
 import io.quarkus.vertx.http.runtime.RouterProducer;
 import io.vertx.core.Handler;
@@ -70,13 +69,4 @@ public io.vertx.ext.web.Route apply(Router router) {
         };
     }
 
-    public void clearCacheOnShutdown(ShutdownContext shutdown) {
-        shutdown.addShutdownTask(new Runnable() {
-            @Override
-            public void run() {
-                RouteHandlers.clear();
-            }
-        });
-    }
-
 }