Repository: quarkusio/quarkus
Issue: Resource not closed warning with rest client

This is a bit hard to reproduce for me. Like in #10804 I am doing remote calls via the MP Rest Client

```
 @Inject
  @RestClient
  RbacServer rbac;
...
   try {
      result = getRbacInfo(user.getRawRhIdHeader());
    } catch (Throwable e) {
...

  @CacheResult(cacheName = "rbac-cache")
  RbacRaw getRbacInfo(String xrhidHeader)  {
    RbacRaw result;
    result = rbac.getRbacInfo("policies", xrhidHeader);  // <---
    return result;
  }
```

And I get (not always) the following in the logs:

`2020-07-17 16:58:30,999 WARN  [org.jbo.res.cli.jax.i18n] (Finalizer) RESTEASY004687: Closing a class org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient43Engine instance for you. Please close clients yourself.
`

Locally I could reproduce it now with the remote service returning a 401, but I also see that on our production instance, where I do not see any errors from the remote call. 

```
2020-07-17 17:38:59,103 WARNING [RbacFilter] (executor-thread-1) Call to RBAC took 1301ms
2020-07-17 17:38:59,102 WARNING [com.git.ben.caf.cac.LocalAsyncCache] (Thread-13) Exception thrown during asynchronous load: java.util.concurrent.CompletionException: javax.ws.rs.WebApplicationException: Unknown error, status code 401
        at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:314)
        at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:319)
        at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1702)
        at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: javax.ws.rs.WebApplicationException: Unknown error, status code 401
        at org.jboss.resteasy.microprofile.client.DefaultResponseExceptionMapper.toThrowable(DefaultResponseExceptionMapper.java:16)
        at org.jboss.resteasy.microprofile.client.ExceptionMapping$HandlerException.mapException(ExceptionMapping.java:38)
        at org.jboss.resteasy.microprofile.client.ProxyInvocationHandler.invoke(ProxyInvocationHandler.java:151)
        at com.sun.proxy.$Proxy75.getRbacInfo(Unknown Source)
        at com.redhat.cloud.policies.app.auth.RbacFilter.getRbacInfo(RbacFilter.java:95)
        at com.redhat.cloud.policies.app.auth.RbacFilter_Subclass.getRbacInfo$$superaccessor1(RbacFilter_Subclass.zig:205)
        at com.redhat.cloud.policies.app.auth.RbacFilter_Subclass$$function$$1.apply(RbacFilter_Subclass$$function$$1.zig:33)
        at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:54)
        at io.quarkus.cache.runtime.CacheResultInterceptor.lambda$intercept$0(CacheResultInterceptor.java:27)
        at io.quarkus.cache.runtime.caffeine.CaffeineCache$MappingSupplier.get(CaffeineCache.java:136)
        at io.quarkus.cache.runtime.caffeine.CaffeineCache.lambda$get$0(CaffeineCache.java:58)
        at com.github.benmanes.caffeine.cache.LocalAsyncCache.lambda$get$0(LocalAsyncCache.java:77)
        at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1700)
        ... 1 more

{"date":"Fri, 17 Jul 2020 15:38:57 GMT","method":"GET","uri":"/api/policies/v1.0/policies/123","acct":"901578","http_version":"HTTP/1.1","status":403,"content_length":0,"duration":1318,"user_agent":"curl/7.54.0","remote":"0:0:0:0:0:0:0:1"}
2020-07-17 17:39:09,854 WARN  [org.jbo.res.cli.jax.i18n] (Finalizer) RESTEASY004687: Closing a class org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient43Engine instance for you. Please close clients yourself.

```

Commenting out the `@CacheResult()` makes the warning/stack trace go away, but still shows the Finalizer-warning.


Changed files:
independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanConfiguratorBase.java
independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/buildextension/beans/BeanRegistrarTest.java
independent-projects/arc/runtime/src/main/java/io/quarkus/arc/BeanDestroyer.java
extensions/rest-client/deployment/src/main/java/io/quarkus/restclient/deployment/RestClientProcessor.java
independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java

diff --git a/extensions/rest-client/deployment/src/main/java/io/quarkus/restclient/deployment/RestClientProcessor.java b/extensions/rest-client/deployment/src/main/java/io/quarkus/restclient/deployment/RestClientProcessor.java
index 60e9667279c..ff9674ec6df 100644
--- a/extensions/rest-client/deployment/src/main/java/io/quarkus/restclient/deployment/RestClientProcessor.java
+++ b/extensions/rest-client/deployment/src/main/java/io/quarkus/restclient/deployment/RestClientProcessor.java
@@ -44,6 +44,7 @@
 import org.jboss.resteasy.microprofile.client.async.AsyncInterceptorRxInvokerProvider;
 import org.jboss.resteasy.spi.ResteasyConfiguration;
 
+import io.quarkus.arc.BeanDestroyer;
 import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
 import io.quarkus.arc.deployment.BeanContainerListenerBuildItem;
 import io.quarkus.arc.deployment.BeanRegistrarBuildItem;
@@ -218,6 +219,7 @@ public void register(RegistrationContext registrationContext) {
                                 MethodDescriptor.ofMethod(RestClientBase.class, "create", Object.class), baseHandle);
                         m.returnValue(ret);
                     });
+                    configurator.destroyer(BeanDestroyer.CloseableDestroyer.class);
                     configurator.done();
                 }
             }
diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanConfiguratorBase.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanConfiguratorBase.java
index 0b9f2097096..ec88d6e85c3 100644
--- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanConfiguratorBase.java
+++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanConfiguratorBase.java
@@ -224,7 +224,7 @@ public <U extends T> B destroyer(Class<? extends BeanDestroyer<U>> destroyerClaz
             ResultHandle destoyerHandle = mc.newInstance(MethodDescriptor.ofConstructor(destroyerClazz));
             ResultHandle[] params = { mc.getMethodParam(0), mc.getMethodParam(1), paramsHandle };
             mc.invokeInterfaceMethod(
-                    MethodDescriptor.ofMethod(BeanDestroyer.class, "destroy", Void.class, Object.class, CreationalContext.class,
+                    MethodDescriptor.ofMethod(BeanDestroyer.class, "destroy", void.class, Object.class, CreationalContext.class,
                             Map.class),
                     destoyerHandle, params);
             mc.returnValue(null);
diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java
index 84745960c68..46958c80e32 100644
--- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java
+++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java
@@ -283,7 +283,7 @@ boolean hasDefaultDestroy() {
             return getLifecycleInterceptors(InterceptionType.PRE_DESTROY).isEmpty()
                     && Beans.getCallbacks(target.get().asClass(), DotNames.PRE_DESTROY, beanDeployment.getIndex()).isEmpty();
         } else {
-            return disposer == null;
+            return disposer == null && destroyerConsumer == null;
         }
     }
 
diff --git a/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/BeanDestroyer.java b/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/BeanDestroyer.java
index f622c382e70..f5580f3e15b 100644
--- a/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/BeanDestroyer.java
+++ b/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/BeanDestroyer.java
@@ -1,5 +1,7 @@
 package io.quarkus.arc;
 
+import java.io.Closeable;
+import java.io.IOException;
 import java.util.Map;
 import javax.enterprise.context.spi.Contextual;
 import javax.enterprise.context.spi.CreationalContext;
@@ -20,4 +22,15 @@
      */
     void destroy(T instance, CreationalContext<T> creationalContext, Map<String, Object> params);
 
+    class CloseableDestroyer implements BeanDestroyer<Closeable> {
+        @Override
+        public void destroy(Closeable instance, CreationalContext<Closeable> creationalContext, Map<String, Object> params) {
+            try {
+                instance.close();
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
 }
diff --git a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/buildextension/beans/BeanRegistrarTest.java b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/buildextension/beans/BeanRegistrarTest.java
index 91a4b1d05f4..544126979f1 100644
--- a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/buildextension/beans/BeanRegistrarTest.java
+++ b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/buildextension/beans/BeanRegistrarTest.java
@@ -10,6 +10,7 @@
 
 import io.quarkus.arc.Arc;
 import io.quarkus.arc.BeanCreator;
+import io.quarkus.arc.BeanDestroyer;
 import io.quarkus.arc.processor.BeanConfigurator;
 import io.quarkus.arc.processor.BeanInfo;
 import io.quarkus.arc.processor.BeanRegistrar;
@@ -25,17 +26,27 @@
 import javax.enterprise.context.spi.CreationalContext;
 import javax.enterprise.util.AnnotationLiteral;
 import javax.inject.Qualifier;
+import javax.inject.Singleton;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
 public class BeanRegistrarTest {
 
+    public static volatile boolean beanDestroyerInvoked = false;
+
     @RegisterExtension
     public ArcTestContainer container = ArcTestContainer.builder()
             .beanClasses(UselessBean.class, MyQualifier.class, NextQualifier.class)
             .removeUnusedBeans(true)
             .beanRegistrars(new TestRegistrar()).build();
 
+    @AfterAll
+    public static void assertDestroyerInvoked() {
+        Assertions.assertTrue(beanDestroyerInvoked);
+    }
+
     @SuppressWarnings("serial")
     static class NextQualifierLiteral extends AnnotationLiteral<NextQualifier> implements NextQualifier {
 
@@ -85,6 +96,8 @@ public void register(RegistrationContext context) {
                 ResultHandle ret = mc.newInstance(MethodDescriptor.ofConstructor(Integer.class, int.class), mc.load(152));
                 mc.returnValue(ret);
             });
+            integerConfigurator.destroyer(SimpleDestroyer.class);
+            integerConfigurator.scope(Singleton.class);
             integerConfigurator.done();
 
             context.configure(String.class).unremovable().types(String.class).param("name", "Frantisek")
@@ -107,6 +120,14 @@ public String create(CreationalContext<String> creationalContext, Map<String, Ob
 
     }
 
+    public static class SimpleDestroyer implements BeanDestroyer<Integer> {
+
+        @Override
+        public void destroy(Integer instance, CreationalContext<Integer> creationalContext, Map<String, Object> params) {
+            beanDestroyerInvoked = true;
+        }
+    }
+
     @Qualifier
     @Inherited
     @Target({ TYPE, METHOD, FIELD, PARAMETER })