Repository: quarkusio/quarkus
Issue: @Produces fails for classes without default constructor

**Describe the bug**
I want to create a bean of a class that has no default constructor and requires some properties to be injected into it. However, since it isn't prepared for CDI, I create a producer class and method to create it with the appropriate values for the properties.

With Quarkus dev, this works just fine. However, when I build the code with `gradlew build` and let it run in a docker container for testing, it fails with `java.lang.NoSuchMethodError: ... method 'void <init>()' not found`. It seems the producer class/method is ignored and ARC tries to instantiate the object itself.

I suspect that this also happens with beans having a default constructor. But then it might not be easy to detect that your producer was ignored. However, I haven't tested that.

This happens with Quarkus 1.4.1.Final and the current master. With Quarkus 1.3.2.Final I get the following error when running quarkus dev or compiling the project: 

```
Caused by: javax.enterprise.inject.spi.DefinitionException: Return type of a producer method for normal scoped beans must declare a non-private constructor with no parameters: PRODUCER METHOD bean [types=[java.lang.Object, com.akamai.netstorage.NetStorage], qualifiers=[@Default, @Any], target=com.akamai.netstorage.NetStorage produceNetStorage(), declaringBean=org.acme.MyProducer]
``` 

Which makes no sense to me. Why would the result of a producer method need to have a default constructor? I'm constructing it for Quarkus, it should not call the default constructor itself.


**Expected behavior**
The producer is used.

**Actual behavior**
The producer is ignored.


**To Reproduce**
Steps to reproduce the behavior:
1. Download reproducer project and unzip it.
[produces-for-non-default-constructor.zip](https://github.com/quarkusio/quarkus/files/4575185/produces-for-non-default-constructor.zip)
2. In the directory run `./gradlew clean quarkusDev` and open localhost:8080/hello in your browser. You should see something like `hello com.akamai.netstorage.NetStorage@26819cc`
3. Compile the project with `./gradlew build` and run the resulting jar. Open the url localhost:8080/hello again. Now you see the following error in the log
```
2020-05-04 14:21:18,306 ERROR [io.qua.ver.htt.run.QuarkusErrorHandler] (executor-thread-1) HTTP Request to /hello failed, error id: 7ed965f0-4c84-4be5-9e87-818f67f360c8-1: java.lang.NoSuchMethodError: com.akamai.netstorage.NetStorage: method 'void <init>()' not found
        at org.acme.MyProducer_ProducerMethod_produceNetStorage_fa2b9b6d18193aaccf98f59e0885e6a21da609e4_ClientProxy.<init>(MyProducer_ProducerMethod_produceNetStorage_fa2b9b6d18193aaccf98f59e0885e6a21da609e4_ClientProxy.zig:414)
        at org.acme.MyProducer_ProducerMethod_produceNetStorage_fa2b9b6d18193aaccf98f59e0885e6a21da609e4_Bean.proxy(MyProducer_ProducerMethod_produceNetStorage_fa2b9b6d18193aaccf98f59e0885e6a21da609e4_Bean.zig:94)
        at org.acme.MyProducer_ProducerMethod_produceNetStorage_fa2b9b6d18193aaccf98f59e0885e6a21da609e4_Bean.get(MyProducer_ProducerMethod_produceNetStorage_fa2b9b6d18193aaccf98f59e0885e6a21da609e4_Bean.zig:115)
        at org.acme.MyProducer_ProducerMethod_produceNetStorage_fa2b9b6d18193aaccf98f59e0885e6a21da609e4_Bean.get(MyProducer_ProducerMethod_produceNetStorage_fa2b9b6d18193aaccf98f59e0885e6a21da609e4_Bean.zig:41)
        at org.acme.Example2Resource_Bean.create(Example2Resource_Bean.zig:109)
        at org.acme.Example2Resource_Bean.create(Example2Resource_Bean.zig:312)
        at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:79)
        at io.quarkus.arc.impl.ComputingCache$CacheFunction.lambda$apply$0(ComputingCache.java:99)
        at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26)
        at io.quarkus.arc.impl.ComputingCache.getValue(ComputingCache.java:41)
        at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:25)
        at org.acme.Example2Resource_ClientProxy.arc$delegate(Example2Resource_ClientProxy.zig:181)
        at org.acme.Example2Resource_ClientProxy.arc_contextualInstance(Example2Resource_ClientProxy.zig:228)
        at io.quarkus.arc.runtime.ClientProxyUnwrapper.apply(ClientProxyUnwrapper.java:11)
        at io.quarkus.resteasy.common.runtime.ResteasyInjectorFactoryRecorder$1.apply(ResteasyInjectorFactoryRecorder.java:22)
        at io.quarkus.resteasy.common.runtime.QuarkusInjectorFactory$UnwrappingPropertyInjector.inject(QuarkusInjectorFactory.java:71)
        at org.jboss.resteasy.plugins.server.resourcefactory.POJOResourceFactory.createResource(POJOResourceFactory.java:79)
        at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:368)
        at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:67)
        at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:488)
        at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:259)
        at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:160)
        at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:362)
        at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:163)
        at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:245)
        at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:73)
        at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:123)
        at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.access$000(VertxRequestHandler.java:36)
        at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler$1.run(VertxRequestHandler.java:87)
        at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
        at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2046)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1578)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1452)
        at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
        at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
        at java.base/java.lang.Thread.run(Thread.java:834)
        at org.jboss.threads.JBossThread.run(JBossThread.java:479)
```

**Configuration**
See reproducer. 

**Screenshots**
(If applicable, add screenshots to help explain your problem.)

**Environment (please complete the following information):**
 - Windows 10
- Java 11
- Quarkus 
  - 1.3.2.Final (throws error on build) 
  - 1.4.1.Final and master (fail during runtime after build but work in quarkusDev)


Changed files:
independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/QuarkusClassLoader.java
core/deployment/src/main/java/io/quarkus/deployment/QuarkusAugmentor.java
independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/ClassPathElement.java
independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/JarClassPathElement.java
independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/MemoryClassPathElement.java
independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/DirectoryClassPathElement.java
core/deployment/src/main/java/io/quarkus/deployment/steps/ClassTransformingBuildStep.java

diff --git a/core/deployment/src/main/java/io/quarkus/deployment/QuarkusAugmentor.java b/core/deployment/src/main/java/io/quarkus/deployment/QuarkusAugmentor.java
index ad9d811713e..f4c19ae3713 100644
--- a/core/deployment/src/main/java/io/quarkus/deployment/QuarkusAugmentor.java
+++ b/core/deployment/src/main/java/io/quarkus/deployment/QuarkusAugmentor.java
@@ -131,12 +131,13 @@ public BuildResult run() throws Exception {
                 rootBuilder.setArchiveLocation(root);
             } else {
                 rootBuilder.setArchiveLocation(effectiveModel.getAppArtifact().getPaths().iterator().next());
+
+                effectiveModel.getAppArtifact().getPaths().forEach(p -> {
+                    if (!p.equals(root)) {
+                        rootBuilder.addArchiveRoot(p);
+                    }
+                });
             }
-            effectiveModel.getAppArtifact().getPaths().forEach(p -> {
-                if (!p.equals(root)) {
-                    rootBuilder.addArchiveRoot(p);
-                }
-            });
             rootBuilder.setExcludedFromIndexing(excludedFromIndexing);
 
             BuildChain chain = chainBuilder.build();
diff --git a/core/deployment/src/main/java/io/quarkus/deployment/steps/ClassTransformingBuildStep.java b/core/deployment/src/main/java/io/quarkus/deployment/steps/ClassTransformingBuildStep.java
index bfc393a1b08..cdbeb0c0572 100644
--- a/core/deployment/src/main/java/io/quarkus/deployment/steps/ClassTransformingBuildStep.java
+++ b/core/deployment/src/main/java/io/quarkus/deployment/steps/ClassTransformingBuildStep.java
@@ -1,6 +1,5 @@
 package io.quarkus.deployment.steps;
 
-import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -23,7 +22,8 @@
 import org.objectweb.asm.ClassVisitor;
 import org.objectweb.asm.ClassWriter;
 
-import io.quarkus.deployment.ApplicationArchive;
+import io.quarkus.bootstrap.classloading.ClassPathElement;
+import io.quarkus.bootstrap.classloading.QuarkusClassLoader;
 import io.quarkus.deployment.QuarkusClassWriter;
 import io.quarkus.deployment.annotations.BuildStep;
 import io.quarkus.deployment.builditem.ApplicationArchivesBuildItem;
@@ -55,6 +55,7 @@ TransformedClassesBuildItem handleClassTransformation(List<BytecodeTransformerBu
                         .addAll(i.getRequireConstPoolEntry());
             }
         }
+        QuarkusClassLoader cl = (QuarkusClassLoader) Thread.currentThread().getContextClassLoader();
         Map<String, Path> transformedToArchive = new ConcurrentHashMap<>();
         // now copy all the contents to the runner jar
         // we also record if any additional archives needed transformation
@@ -66,46 +67,46 @@ TransformedClassesBuildItem handleClassTransformation(List<BytecodeTransformerBu
             for (Map.Entry<String, List<BiFunction<String, ClassVisitor, ClassVisitor>>> entry : bytecodeTransformers
                     .entrySet()) {
                 String className = entry.getKey();
-                Set<String> constValues = constScanning.get(className);
-                ApplicationArchive archive = appArchives.containingArchive(entry.getKey());
-                if (archive != null) {
+                String classFileName = className.replace(".", "/") + ".class";
+                List<ClassPathElement> archives = cl.getElementsWithResource(classFileName);
+                if (!archives.isEmpty()) {
+                    ClassPathElement classPathElement = archives.get(0);
+                    Path jar = classPathElement.getRoot();
+                    if (jar == null) {
+                        log.warnf("Cannot transform %s as it's containing application archive could not be found.",
+                                entry.getKey());
+                        continue;
+                    }
                     List<BiFunction<String, ClassVisitor, ClassVisitor>> visitors = entry.getValue();
-                    String classFileName = className.replace(".", "/") + ".class";
-                    archive.processEntry(classFileName, (classFile, jar) -> {
-                        transformedToArchive.put(classFileName, jar);
-                        transformed.add(executorPool.submit(new Callable<TransformedClassesBuildItem.TransformedClass>() {
-                            @Override
-                            public TransformedClassesBuildItem.TransformedClass call() throws Exception {
-                                ClassLoader old = Thread.currentThread().getContextClassLoader();
-                                try {
-                                    Thread.currentThread().setContextClassLoader(transformCl);
-                                    if (Files.size(classFile) > Integer.MAX_VALUE) {
-                                        throw new RuntimeException(
-                                                "Can't process class files larger than Integer.MAX_VALUE bytes");
+                    transformedToArchive.put(classFileName, jar);
+                    transformed.add(executorPool.submit(new Callable<TransformedClassesBuildItem.TransformedClass>() {
+                        @Override
+                        public TransformedClassesBuildItem.TransformedClass call() throws Exception {
+                            ClassLoader old = Thread.currentThread().getContextClassLoader();
+                            try {
+                                Thread.currentThread().setContextClassLoader(transformCl);
+                                byte[] classData = classPathElement.getResource(classFileName).getData();
+                                Set<String> constValues = constScanning.get(className);
+                                if (constValues != null && !noConstScanning.contains(className)) {
+                                    if (!ConstPoolScanner.constPoolEntryPresent(classData, constValues)) {
+                                        return null;
                                     }
-                                    byte[] classData = Files.readAllBytes(classFile);
-
-                                    if (constValues != null && !noConstScanning.contains(className)) {
-                                        if (!ConstPoolScanner.constPoolEntryPresent(classData, constValues)) {
-                                            return null;
-                                        }
-                                    }
-                                    ClassReader cr = new ClassReader(classData);
-                                    ClassWriter writer = new QuarkusClassWriter(cr,
-                                            ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
-                                    ClassVisitor visitor = writer;
-                                    for (BiFunction<String, ClassVisitor, ClassVisitor> i : visitors) {
-                                        visitor = i.apply(className, visitor);
-                                    }
-                                    cr.accept(visitor, 0);
-                                    return new TransformedClassesBuildItem.TransformedClass(writer.toByteArray(),
-                                            classFileName);
-                                } finally {
-                                    Thread.currentThread().setContextClassLoader(old);
                                 }
+                                ClassReader cr = new ClassReader(classData);
+                                ClassWriter writer = new QuarkusClassWriter(cr,
+                                        ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
+                                ClassVisitor visitor = writer;
+                                for (BiFunction<String, ClassVisitor, ClassVisitor> i : visitors) {
+                                    visitor = i.apply(className, visitor);
+                                }
+                                cr.accept(visitor, 0);
+                                return new TransformedClassesBuildItem.TransformedClass(writer.toByteArray(),
+                                        classFileName);
+                            } finally {
+                                Thread.currentThread().setContextClassLoader(old);
                             }
-                        }));
-                    });
+                        }
+                    }));
                 } else {
                     log.warnf("Cannot transform %s as it's containing application archive could not be found.",
                             entry.getKey());
diff --git a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/ClassPathElement.java b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/ClassPathElement.java
index 7247d1f658f..251ea050b9c 100644
--- a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/ClassPathElement.java
+++ b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/ClassPathElement.java
@@ -15,6 +15,12 @@
  */
 public interface ClassPathElement extends Closeable {
 
+    /**
+     *
+     * @return The element root, or null if not applicable
+     */
+    Path getRoot();
+
     /**
      * Loads a resource from the class path element, or null if it does not exist.
      *
@@ -46,6 +52,11 @@ static ClassPathElement fromPath(Path path) {
     }
 
     static ClassPathElement EMPTY = new ClassPathElement() {
+        @Override
+        public Path getRoot() {
+            return null;
+        }
+
         @Override
         public ClassPathResource getResource(String name) {
             return null;
diff --git a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/DirectoryClassPathElement.java b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/DirectoryClassPathElement.java
index 80c2cdb86e1..f2f13173380 100644
--- a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/DirectoryClassPathElement.java
+++ b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/DirectoryClassPathElement.java
@@ -29,6 +29,11 @@ public DirectoryClassPathElement(Path root) {
         this.root = root;
     }
 
+    @Override
+    public Path getRoot() {
+        return root;
+    }
+
     @Override
     public ClassPathResource getResource(String name) {
         Path file = root.resolve(name);
diff --git a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/JarClassPathElement.java b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/JarClassPathElement.java
index a559b3188c4..687ee5a0df3 100644
--- a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/JarClassPathElement.java
+++ b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/JarClassPathElement.java
@@ -32,18 +32,25 @@ public class JarClassPathElement implements ClassPathElement {
     private static final Logger log = Logger.getLogger(JarClassPathElement.class);
     private final File file;
     private final URL jarPath;
+    private final Path root;
     private JarFile jarFile;
     private boolean closed;
 
     public JarClassPathElement(Path root) {
         try {
             jarPath = root.toUri().toURL();
+            this.root = root;
             jarFile = new JarFile(file = root.toFile());
         } catch (IOException e) {
             throw new UncheckedIOException("Error while reading file as JAR: " + root, e);
         }
     }
 
+    @Override
+    public Path getRoot() {
+        return root;
+    }
+
     @Override
     public synchronized ClassPathResource getResource(String name) {
         return withJarFile(new Function<JarFile, ClassPathResource>() {
diff --git a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/MemoryClassPathElement.java b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/MemoryClassPathElement.java
index b6769276f91..94c5baa2a79 100644
--- a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/MemoryClassPathElement.java
+++ b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/MemoryClassPathElement.java
@@ -7,6 +7,7 @@
 import java.net.URL;
 import java.net.URLConnection;
 import java.net.URLStreamHandler;
+import java.nio.file.Path;
 import java.security.CodeSource;
 import java.security.ProtectionDomain;
 import java.security.cert.Certificate;
@@ -40,6 +41,11 @@ public void reset(Map<String, byte[]> resources) {
         this.resources = newResources;
     }
 
+    @Override
+    public Path getRoot() {
+        return null;
+    }
+
     @Override
     public ClassPathResource getResource(String name) {
         byte[] res = resources.get(name);
diff --git a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/QuarkusClassLoader.java b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/QuarkusClassLoader.java
index 0fb4bef3829..791ba274471 100644
--- a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/QuarkusClassLoader.java
+++ b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/QuarkusClassLoader.java
@@ -398,6 +398,17 @@ private void definePackage(String name, ClassPathElement classPathElement) {
         }
     }
 
+    private String getPackageNameFromClassName(String className) {
+        final int index = className.lastIndexOf('.');
+        if (index == -1) {
+            // we return null here since in this case no package is defined
+            // this is same behavior as Package.getPackage(clazz) exhibits
+            // when the class is in the default package
+            return null;
+        }
+        return className.substring(0, index);
+    }
+
     public List<ClassPathElement> getElementsWithResource(String name) {
         List<ClassPathElement> ret = new ArrayList<>();
         if (parent instanceof QuarkusClassLoader) {
@@ -411,17 +422,6 @@ public List<ClassPathElement> getElementsWithResource(String name) {
         return ret;
     }
 
-    private String getPackageNameFromClassName(String className) {
-        final int index = className.lastIndexOf('.');
-        if (index == -1) {
-            // we return null here since in this case no package is defined
-            // this is same behavior as Package.getPackage(clazz) exhibits
-            // when the class is in the default package
-            return null;
-        }
-        return className.substring(0, index);
-    }
-
     private byte[] handleTransform(String name, byte[] bytes,
             List<BiFunction<String, ClassVisitor, ClassVisitor>> transformers,
             Map<String, Predicate<byte[]>> transformerPredicates) {