Repository: quarkusio/quarkus
Issue: NullPointerException on generic injection with quarkus-arc

**Describe the bug**
Following the https://github.com/quarkusio/quarkus/issues/2456 issue correction on master, I just ran a quick test with a snapshot version of quarkus. My unsatisfied dependency problem is gone (thanks for that!) but I have now an injection issue at runtime.

**Expected behavior**
I expect injections to work with generics.

**Actual behavior**
```
2019-05-22 23:10:52,098 ERROR [io.und.request] (executor-thread-1) UT005023: Exception handling request to /cars: org.jboss.resteasy.spi.UnhandledException: java.lang.NullPointerException
        at org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:106)
        at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:372)
        at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:209)
        at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:496)
        at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:252)
        at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:153)
        at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:362)
        at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:156)
        at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:238)
        at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:234)
        at io.quarkus.resteasy.runtime.ResteasyFilter$ResteasyResponseWrapper.sendError(ResteasyFilter.java:72)
        at io.undertow.servlet.handlers.DefaultServlet.doGet(DefaultServlet.java:175)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:686)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:791)
        at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
        at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
        at io.quarkus.resteasy.runtime.ResteasyFilter.doFilter(ResteasyFilter.java:43)
        at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
        at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
        at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
        at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
        at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
        at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
        at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132)
        at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
        at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
        at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
        at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
        at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292)
        at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81)
        at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138)
        at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135)
        at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
        at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
        at io.quarkus.undertow.runtime.UndertowDeploymentTemplate$7$1$1.call(UndertowDeploymentTemplate.java:437)
        at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)
        at io.undertow.servlet.handlers.ServletInitialHandler.handleRequest(ServletInitialHandler.java:197)
        at io.undertow.server.handlers.HttpContinueReadHandler.handleRequest(HttpContinueReadHandler.java:65)
        at io.quarkus.undertow.runtime.UndertowDeploymentTemplate$1.handleRequest(UndertowDeploymentTemplate.java:96)
        at io.undertow.server.handlers.CanonicalPathHandler.handleRequest(CanonicalPathHandler.java:49)
        at io.quarkus.undertow.deployment.devmode.UndertowHotReplacementSetup.handleHotDeploymentRequest(UndertowHotReplacementSetup.java:80)
        at io.quarkus.undertow.deployment.devmode.UndertowHotReplacementSetup$1$1.handleRequest(UndertowHotReplacementSetup.java:51)
        at io.undertow.server.Connectors.executeRootHandler(Connectors.java:364)
        at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
        at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
        at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2011)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1538)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1395)
        at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
        at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:32)
        at java.base/java.lang.Thread.run(Thread.java:834)
        at org.jboss.threads.JBossThread.run(JBossThread.java:479)
Caused by: java.lang.NullPointerException
        at com.gwenneg.CarResource.inject(CarResource.java:21)
        at com.gwenneg.CarResource_ClientProxy.inject(Unknown Source)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:151)
        at org.jboss.resteasy.core.MethodInjectorImpl.lambda$invoke$3(MethodInjectorImpl.java:122)
        at java.base/java.util.concurrent.CompletableFuture.uniApplyNow(CompletableFuture.java:680)
        at java.base/java.util.concurrent.CompletableFuture.uniApplyStage(CompletableFuture.java:658)
        at java.base/java.util.concurrent.CompletableFuture.thenApply(CompletableFuture.java:2094)
        at java.base/java.util.concurrent.CompletableFuture.thenApply(CompletableFuture.java:143)
        at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:122)
        at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:568)
        at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:442)
        at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:396)
        at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:362)
        at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:398)
        at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:367)
        at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invoke$1(ResourceMethodInvoker.java:341)
        at java.base/java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:1106)
        at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2235)
        at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:143)
        at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:341)
        at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:477)
        ... 53 more
```

**To Reproduce**
Steps to reproduce the behavior:
1. Clone https://github.com/gwenneg/quarkus-unsatisfied-dependency
2. Run the `./gradlew quarkusDev` or `./mvnw compile quarkus:dev` command
3. Call the endpoint using `http://localhost:8080/cars`

**Environment:**
 - Output of `java -version`: openjdk version "11" 2018-09-25
 - Quarkus version or git rev: master (https://github.com/quarkusio/quarkus/commit/903dea163ea37e59135c5a3db11d24137b82a62a)

Changed files:
independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanGenerator.java
independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Methods.java
independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/injection/assignability/generics/AssignabilityWithGenericsTest.java
independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/injection/assignability/generics/Vehicle.java

diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanGenerator.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanGenerator.java
index 2d8929fe336..2f527cecf34 100644
--- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanGenerator.java
+++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanGenerator.java
@@ -982,9 +982,11 @@ protected void implementCreate(ClassOutput classOutput, ClassCreator beanCreator
                             create.load(injectedField.name()), instanceHandle, referenceHandle);
 
                 } else {
+                    // We cannot use injectionPoint.getRequiredType() because it might be a resolved parameterize type and we could get NoSuchFieldError
+                    String fieldType = injectionPoint.getTarget().asField().type().name().toString();
                     create.writeInstanceField(
                             FieldDescriptor.of(providerTypeName, injectedField.name(),
-                                    injectionPoint.getRequiredType().name().toString()),
+                                    fieldType),
                             instanceHandle, referenceHandle);
                 }
             }
diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Methods.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Methods.java
index c9564e9bbd8..4a247131663 100644
--- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Methods.java
+++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Methods.java
@@ -65,7 +65,7 @@ static void addDelegatingMethods(IndexView index, ClassInfo classInfo, Map<TypeV
                 }
                 methods.computeIfAbsent(new Methods.MethodKey(method), key -> {
                     // If parameterized try to resolve the type variables
-                    Type returnType = resolveType(key.method.returnType(), resolvedTypeParameters);
+                    Type returnType = key.method.returnType();
                     Type[] params = new Type[key.method.parameters().size()];
                     for (int i = 0; i < params.length; i++) {
                         params[i] = resolveType(key.method.parameters().get(i), resolvedTypeParameters);
diff --git a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/injection/assignability/generics/AssignabilityWithGenericsTest.java b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/injection/assignability/generics/AssignabilityWithGenericsTest.java
index 630b5dff21a..8d90422e782 100644
--- a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/injection/assignability/generics/AssignabilityWithGenericsTest.java
+++ b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/injection/assignability/generics/AssignabilityWithGenericsTest.java
@@ -1,8 +1,11 @@
 package io.quarkus.arc.test.injection.assignability.generics;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 import io.quarkus.arc.Arc;
+import io.quarkus.arc.InstanceHandle;
 import io.quarkus.arc.test.ArcTestContainer;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -21,22 +24,51 @@ public class AssignabilityWithGenericsTest {
 
     @Rule
     public ArcTestContainer container = new ArcTestContainer(Car.class, Engine.class, PetrolEngine.class, Vehicle.class,
-            StringListConsumer.class, ListConsumer.class, ProducerBean.class, DefinitelyNotBar.class, Bar.class,
-            GenericInterface.class, AlmostCompleteBean.class, ActualBean.class);
+            StringListConsumer.class, ListConsumer.class, ProducerBean.class, DefinitelyNotBar.class,
+            Bar.class, GenericInterface.class, AlmostCompleteBean.class, ActualBean.class,
+            BetaFace.class, GammaFace.class, GammaImpl.class, AbstractAlpha.class, AlphaImpl.class);
 
     @Test
     public void testSelectingInstanceOfCar() {
-        assertTrue(Arc.container().instance(Car.class).isAvailable());
+        InstanceHandle<Car> instance = Arc.container().instance(Car.class);
+        assertTrue(instance.isAvailable());
+        assertNotNull(instance.get().getEngine());
     }
 
     @Test
     public void testParameterizedTypeWithTypeVariable() {
-        assertTrue(Arc.container().instance(StringListConsumer.class).isAvailable());
+        InstanceHandle<StringListConsumer> instance = Arc.container().instance(StringListConsumer.class);
+        assertTrue(instance.isAvailable());
+        assertNotNull(instance.get().getList());
     }
 
     @Test
     public void testHierarchyWithInterfacesAndMap() {
-        assertTrue(Arc.container().instance(ActualBean.class).isAvailable());
+        InstanceHandle<ActualBean> instance = Arc.container().instance(ActualBean.class);
+        assertTrue(instance.isAvailable());
+        assertNotNull(instance.get().getInjectedMap());
+    }
+
+    @Test
+    public void testProxiedBeanWithGenericMethodParams() {
+        InstanceHandle<AlphaImpl> alphaInstance = Arc.container().instance(AlphaImpl.class);
+        InstanceHandle<GammaImpl> gammaInstance = Arc.container().instance(GammaImpl.class);
+        assertTrue(alphaInstance.isAvailable());
+        assertTrue(gammaInstance.isAvailable());
+        AlphaImpl alpha = alphaInstance.get();
+        assertEquals(GammaImpl.class.getSimpleName(), alpha.ping(alpha.getParam()));
+    }
+
+    interface GenericInterface<T, K> {
+
+    }
+
+    interface BetaFace<K> {
+        K ping();
+    }
+
+    interface GammaFace extends BetaFace<String> {
+
     }
 
     @Dependent
@@ -48,11 +80,18 @@ static class StringListConsumer extends ListConsumer<String> {
 
         @Inject
         List<T> list;
+
+        public List<T> getList() {
+            return list;
+        }
     }
 
     @Dependent
     static class ProducerBean {
 
+        @Produces
+        String foo = "foo";
+
         @Produces
         List<String> produceList() {
             return new ArrayList<>();
@@ -63,13 +102,6 @@ Map<String, Bar> produceMap() {
             return new HashMap<>();
         }
 
-        @Produces
-        String foo = "foo";
-
-    }
-
-    static interface GenericInterface<T, K> {
-
     }
 
     static class DefinitelyNotBar<D> {
@@ -92,6 +124,10 @@ public void observeSomething(@Observes String event, T injectedInstance) {
         public void observeSomethingElse(@ObservesAsync String event, K injectedInstance) {
             // inject-ability is verified at bootstrap
         }
+
+        public Map<T, K> getInjectedMap() {
+            return injectedMap;
+        }
     }
 
     @ApplicationScoped
@@ -99,4 +135,33 @@ static class ActualBean extends AlmostCompleteBean<String, Bar> {
 
     }
 
+    @ApplicationScoped
+    static class GammaImpl implements GammaFace {
+
+        @Override
+        public String ping() {
+            return GammaImpl.class.getSimpleName();
+        }
+    }
+
+    static abstract class AbstractAlpha<T extends BetaFace> {
+
+        @Inject
+        T param;
+
+        public T getParam() {
+            return param;
+        }
+
+        public String ping(T param) {
+            return param.ping().toString();
+        }
+
+    }
+
+    @ApplicationScoped
+    static class AlphaImpl extends AbstractAlpha<GammaFace> {
+
+    }
+
 }
diff --git a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/injection/assignability/generics/Vehicle.java b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/injection/assignability/generics/Vehicle.java
index 291ff8a272d..cd468d64132 100644
--- a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/injection/assignability/generics/Vehicle.java
+++ b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/injection/assignability/generics/Vehicle.java
@@ -6,4 +6,8 @@
 
     @Inject
     T eng;
+
+    public T getEngine() {
+        return eng;
+    }
 }