{{announcement.body}}
{{announcement.title}}

Spring Boot - Async methods

DZone 's Guide to

Spring Boot - Async methods

Get some clarity on async methods with this tutorial that demonstrates how to enable them and annotate the related methods.

· Java Zone ·
Free Resource

The key steps behind enabling Async methods in Spring are here:

1) Enable async processing in Spring Boot by annotation Spring Boot Application class with @EnableAsync

2) Create a ThreadPoolExecutor to run async methods in separate threads

3) Annotate the methods that need to be run in separate threads with @Async annotation 

This is explained in the blog post at the Spring site.

 I had a look at it and then started applying the changes in the project accordingly. It worked fine and solved the issues that we faced with performance.

In that blog post, usage of Async method was explained by creating a service method, annotated with @Asyncannotation, that makes a call to GitHub API.  

While reading the post, couple of things that struck me in that blog post:

1) When using Async methods, the return type of method must be CompletableFuture

2)  Following are the lines of code that make a call to Async service method

Code to make a call to Async service method


During debug in Eclipse, I was able to go from Line 1 to Line 2 without waiting for the service method to return the results . But I was puzzled as to how the variable in page1 got populated with the return value of the service method after the control has gone beyond Line 1.

The service method is like this:

Java
 




xxxxxxxxxx
1
10
9


 
1
  @Async
2
  public CompletableFuture<User> findUser(String user) throws InterruptedException {
3
    logger.info("Looking up " + user);
4
    String url = String.format("https://api.github.com/users/%s", user);
5
    User results = restTemplate.getForObject(url, User.class);
6
    // Artificial delay of 1s for demonstration purposes
7
    Thread.sleep(1000L);
8
    return CompletableFuture.completedFuture(results); //IT IS completedFuture
9
  }


The service method does not encapsulate the whole process in the CompletableFuture, rather all the processing is done and then at the end CompletableFuture was created to hold the results. So how is the asynchronous nature is achieved?

I started debugging. Following are my observations.

Whenever any method is annotated with @Async annotation, Spring automatically creates a proxy object for that class and injects that proxy into other classes that depend on this class. So any call to the async method goes through the proxy.

A class AsyncExecutionInterceptor intercepts the Asyncmethod calls  and  creates a CompletableFuture object and returns it.

CompletableFuture

Now the question is this. Since this interceptor class is creating CompletableFuture, why should the service method also need to do the same. Can the service method just return the object instead of wrapping it in a CompletableFuture?

The answer is "No", because the interceptor is actually called by proxy that Spring has created. To achieve async nature for methods, usage of CompletableFuture is necessary. 

But, we cannot have different return types for actual method and the method present in the proxy. Both must have same return type. That is the reason that even the service method must return value wrapped in a CompletedFuture. 

Hope this helps in understanding async methods better.

Topics:
annotations, async methods, spring boot, threadpoolexecutor, threads

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}