title: Spring cloud @HystrixCommand doesn't proxy the method which is invoked in CompletableFuture.supplyAsync
body: <p>I have one spring component bean which contains a method <strong>methodA</strong> defined by @HystrixCommand with fallbackMethod. The bean has another method <strong>methodB</strong> invokes <strong>methodA</strong> by CompletableFuture.supplyAsync(...). I expect Hystrix javanica will weave the aspect on <strong>methodA</strong>, but when I debug it, I didn't see hystrix aspect is weaved.</p>
  
  <p>Here are some of the main sudo code,</p>
  
  <p><strong>TestApplication</strong>:</p>
  
  <pre><code>package com.my.own.test;
  
  import org.springframework.boot.SpringApplication;
  import org.springframework.boot.autoconfigure.SpringBootApplication;
  
  @SpringBootApplication(scanBasePackages = "com.my.own.test")
  public class TestApplication {
      public static void main(final String[] args) throws Exception {
          SpringApplication.run(TestApplication.class, args);
      }
  }
  </code></pre>
  
  <p><strong>ApplicationConfiguration</strong>:</p>
  
  <pre><code>package com.my.own.test;
  
  import org.springframework.boot.context.properties.EnableConfigurationProperties;
  import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
  import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.Configuration;
  import org.springframework.context.annotation.EnableAspectJAutoProxy;
  
  @Configuration
  @EnableAspectJAutoProxy(exposeProxy = true)
  @EnableConfigurationProperties
  @EnableCircuitBreaker
  public class ApplicationConfig {
  
  }
  </code></pre>
  
  <p><strong>AsyncConfig</strong>:</p>
  
  <pre><code>package com.my.own.test;
  
  import org.springframework.beans.factory.annotation.Value;
  import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.Configuration;
  import org.springframework.scheduling.annotation.EnableAsync;
  import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
  
  @Configuration
  @EnableAsync
  public class AsyncConfig {
  
     @Value("${spring.threadpool.executor.core:10}")
     private int corePoolSize;
  
     @Value("${spring.threadpool.executor.max:20}")
     private int maxPoolSize;
  
     @Value("${spring.threadpool.executor.queue:1000}")
     private int queueCapacity;
  
     @Value("${spring.threadpool.executor.timeout:true}")
     private boolean coreThreadTimeOut;
  
     @Value("${spring.threadpool.executor.keepalive:30000}")
     private int keepAlive;
  
     @Value("${spring.threadpool.executor.prefix:ThreadPoolTaskExecutor}")
     private String threadNamePrefix;
  
     @Bean("taskExecutor")
     public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
         final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
         executor.setCorePoolSize(corePoolSize);
         executor.setMaxPoolSize(maxPoolSize);
         executor.setQueueCapacity(queueCapacity);
         executor.setAllowCoreThreadTimeOut(coreThreadTimeOut);
         executor.setKeepAliveSeconds(keepAlive);
         executor.setThreadNamePrefix(threadNamePrefix + "-");
         executor.initialize();
  
         return executor;
     }
  }
  </code></pre>
  
  <p><strong>TestController</strong>:</p>
  
  <pre><code>package com.my.own.test.controller;
  
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.web.bind.annotation.RequestMapping;
  import org.springframework.web.bind.annotation.RequestMethod;
  import org.springframework.web.bind.annotation.RestController;
  import com.my.own.test.core.TestProcessor;
  
  @RestController
  public class TestController {
  
      private static Logger logger = LoggerFactory.getLogger(TestController.class);
  
      @Autowired
      TestProcessor tester;
  
      @RequestMapping(value = "/test", method = { RequestMethod.POST })
      public void test() {
          tester.methodB();
      }
  }
  </code></pre>
  
  <p><strong>TestProcessor</strong>:</p>
  
  <pre><code>package com.my.own.test.core;
  
  import java.util.ArrayList;
  import java.util.List;
  import java.util.concurrent.CompletableFuture;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
  import org.springframework.stereotype.Component;
  import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
  
  @Component
  public class TestProcessor {
  
      @Autowired
      private ThreadPoolTaskExecutor executor;
  
      public void methodB() {
          final List&lt;CompletableFuture&lt;String&gt;&gt; a = new ArrayList&lt;&gt;();
          a.add(CompletableFuture.supplyAsync(() -&gt; methodA(), executor));
          CompletableFuture.allOf(a.toArray(new CompletableFuture[a.size()])).join();
      }
  
      @HystrixCommand(fallbackMethod = "deferPushdown")
      public String methodA() {
          if (true) {
              throw new RuntimeException();
          } else {
              return "methodA";
          }
      }
  
      public String deferMethodA() {
          return "deferMethodA";
      }
  }
  </code></pre>
  
  <p><strong>Run output</strong></p>
  
  <pre><code>Jan 03, 2018 2:55:55 PM org.apache.catalina.core.StandardWrapperValve invoke
  SEVERE: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.util.concurrent.CompletionException: java.lang.RuntimeException] with root cause
  java.lang.RuntimeException
      at com.my.own.test.core.TestProcessor.methodA(TestProcessor.java:40)
      at com.my.own.test.core.TestProcessor.lambda$0(TestProcessor.java:33)
      at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
      at java.lang.Thread.run(Thread.java:745)
  </code></pre>
  
  <p>P.S.
  From the output, methodA is not invoked from hystrix aspect, but by lambda directly. Is this an issue on Hystrix or javanica? Please share if you know a solution. I appreciate it.</p>