@Async in Spring

In this tutorial, we will discuss the asynchronous execution support in Spring and the @Async annotation. There are cases in which it is necessary to execute pieces of code asynchronous. An example is the sending of a (JMS) message from your system to another system. The advantage is that the user does not have to wait in the front-end while the message is being sent. Another example of possible asynchronous execution is the case where messages have a clear ordering.

Annotating a method of a bean with @Async will make it execute in a separate thread i.e. the caller will not wait for the completion of the called method.

Enable Async Support
The @EnableAsync annotation switches on Spring’s ability to run @Async methods in a background thread pool. For Enabling asynchronous processing with Java configuration got by simply adding the @EnableAsync to a configuration class:

@Configuration
@EnableAsync
public class SpringAsyncConfig { ... }

Asynchronous processing can also be enabled using XML configuration – by using the task namespace:

<task:executor id="myexecutor" pool-size="5"  />
<task:annotation-driven executor="myexecutor"/>


Limitations for @Async

  1. it must be applied to public methods only
  2. self invocation – calling the async method from within the same class – won’t work

The reasons are simple – the method needs to be public so that it can be proxied. And self-invocation doesn’t work because it bypasses the proxy and calls the underlying method directly.

The @Async Annotation
Annotation that marks a method as a candidate for asynchronous execution. Can also be used at the type level, in which case all of the type’s methods are considered as asynchronous.

1. Methods with void Return Type
Following is the simple way to configure a method with void return type to run asynchronously:

@Async
public void asyncMethodWithVoidReturnType() {
    System.out.println("Execute method asynchronously. "
      + Thread.currentThread().getName());
}

2. Methods With Return Type
@Async can also be applied to a method with return type – by wrapping the actual return in a Future:

@Service
public class GitHubLookupService {

    RestTemplate restTemplate = new RestTemplate();

    @Async
    public Future<User> findUser(String user) throws InterruptedException {
        System.out.println("Looking up " + user);
        User results = restTemplate.getForObject("https://api.github.com/users/" + user, User.class);
        // Artificial delay of 1s for demonstration purposes
        Thread.sleep(1000L);
        return new AsyncResult<User>(results);
    }

}

Spring also provides an AsyncResult class which implements Future. This can be used to track the result of the asynchronous method execution.

Now, let’s invoke the above method and retrieve the result of the asynchronous process using the Future object

public void testAsyncAnnotationForMethodsWithReturnType()
    throws InterruptedException, ExecutionException {
    System.out.println("Invoking an asynchronous method. "
      + Thread.currentThread().getName());
    Future<User> future = GitHubLookupService.findUser(user);
 
    while (true) {
        if (future.isDone()) {
            System.out.println("Result from asynchronous process - " + future.get());
            break;
        }
        System.out.println("Continue doing something else. ");
        Thread.sleep(1000);
    }
}

The Executor
By default, Spring uses a SimpleAsyncTaskExecutor to actually run these methods asynchronously. The defaults can be overridden at two levels – at the application level or at the individual method level.
1. Override the Executor at the Method Level

@Configuration
@EnableAsync
public class SpringAsyncConfig {
     
    @Bean(name = "threadPoolTaskExecutor")
    public Executor threadPoolTaskExecutor() {
        return new ThreadPoolTaskExecutor();
    }
}

Then the executor name should be provided as an attribute in @Async:

@Async("threadPoolTaskExecutor")
public void asyncMethodWithConfiguredExecutor() {
    System.out.println("Execute method with configured executor - "
      + Thread.currentThread().getName());
}

2. Override the Executor at the Application Level

@Configuration
@EnableAsync
public class SpringAsyncConfig implements AsyncConfigurer {
     
    @Override
    public Executor getAsyncExecutor() {
        return new ThreadPoolTaskExecutor();
    }
     
}

The configuration class should implement the AsyncConfigurer interface – which will mean that it has the implement the getAsyncExecutor() method. It’s here that we will return the executor for the entire application – this now becomes the default executor to run methods annotated with @Async.

Exception Handling
We’ll create a custom async exception handler by implementing AsyncUncaughtExceptionHandler interface. The handleUncaughtException() method is invoked when there are any uncaught asynchronous exceptions:

public class CustomAsyncExceptionHandler  implements AsyncUncaughtExceptionHandler {
 
    @Override
    public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
        System.out.println("Exception message - " + throwable.getMessage());
        System.out.println("Method name - " + method.getName());
        for (Object param : obj) {
            System.out.println("Parameter value - " + param);
        }
    }
     
}

When a method return type is a Future, exception handling is easy – Future.get() method will throw the exception.

But, if the return type is void, exceptions will not be propagated to the calling thread. Hence we need to add extra configurations to handle exceptions.

we also need to override the getAsyncUncaughtExceptionHandler() method to return our custom asynchronous exception handler:

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    return new CustomAsyncExceptionHandler();
}

Summary:
Congratulations! You’ve learned an asynchronous service. And also we have seen how to enable async call in spring framework.

Happy Spring Learning.

Spring Related Topics you may like

  1. Spring Interview Questions and Answers
  2. Spring AOP Interview Questions and Answers
  3. Spring MVC Interview Questions
  4. Spring Security Interview Questions and Answers
  5. Spring REST Interview Questions and Answers
  6. Spring Boot Interview Questions and Answers
  7. Spring Boot Microservices Interview Questions and Answers
  8. Dependency Injection (DI) in Spring
  9. Spring IoC Container
  10. What is Bean Factory in Spring
  11. ApplicationContext in Spring
  12. Bean Autowiring in Spring
  13. Spring Bean Scopes
  14. Create Custom Bean Scope in Spring Example
  15. Using ApplicationContextAware in Spring
  16. Spring Bean Life Cycle and Callbacks
  17. BeanPostProcessor in Spring
  18. BeanFactoryPostProcessor in Spring
  19. Annotations in Spring and Based Configuration
  20. Spring JSR-250 Annotations
  21. JSR 330 Annotations in Spring
  22. Spring @Component, @Repository, @Service and @Controller Stereotype Annotations
  23. Method injection with Spring using Lookup method property
  24. Spring AOP-Introduction to Aspect Oriented Programming
  25. @Aspect Annotation in Spring
  26. Spring AOP AspectJ @Before Annotation Advice Example
  27. Spring AOP Before Advice Example using XML Config
  28. Spring AOP AspectJ @After Annotation Advice Example
  29. Spring AOP After Advice Example using XML Config
  30. Spring AOP AspectJ @AfterReturning Annotation Advice Example
  31. Spring AOP After-Returning Advice Example using XML Config
  32. Spring AOP AspectJ @AfterThrowing Annotation Advice Example
  33. Spring AOP After Throwing Advice Example using XML Config
  34. Spring AOP AspectJ @Around Annotation Advice Example
  35. Spring AOP Around Advice Example using XML Config
  36. Spring AOP Proxies in Spring
  37. Spring AOP Transaction Management in Hibernate
  38. Spring Transaction Management
  39. Spring Declarative Transaction Management Example
  40. Spring AOP-Ordering of Aspects with Example
  41. Spring Security Java Based Configuration with Example
  42. Spring Security XML Namespace Configuration Example
Previous
Next

2 Comments

  1. Sunny March 30, 2019
  2. Dinesh Rajput April 25, 2019