Search code examples
springspring-bootspring-cloudhystrix

Hystrix and Spring @Async in combination


I'm using Hystrix library for the Spring Boot project (spring-cloud-starter-hystrix). I have a @Service class annotated with @HystrixCommand and it works as expected.

But, when I add the method annotated with @Async in that same service class then the Hystrix doesn't work, and fallback method is never called. What could cause this problem and how to fix it?

This is the Application class:

@EnableCircuitBreaker
@EnableHystrixDashboard
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
        
    }
}

This is the service class:

@Service
public class TemplateService {

    @HystrixCommand(
            fallbackMethod = "getGreetingFallback",
            commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")}
    )
    public String getGreeting() {
        URI uri = URI.create("http://localhost:8090/greeting");

        ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.GET, null, String.class);
        if (response.getStatusCode().equals(HttpStatus.OK)) {
            return response.getBody();
        } else {
            return null;
        }
    }

    public String getGreetingFallback(Throwable e) {
        return null;
    }

    @Async
    public void async(String message) {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        logger.info(MessageFormat.format("Received async message {0}", message));
    }
}

@EnableAsync annotation is placed in a different class annotated with @Configuration, where I set some other Thread Executor options from properties file.


Solution

  • Given the code for TemplateService (which doesn't implement interface) and assuming the defaults on @EnableAsync it is safe to concur that CGLIB proxies are created by spring.

    Thus the @HystrixCommand annotation on getGreeting() isn't inherited by the service proxy class; which explains the reported behavior.

    To get past this error keep the @HystrixCommand and @Async method separated in different service because enabling JDK proxies will also not help and I am not sure about AspectJ mode.

    Refer this for further information on Spring proxy mechanism.