How to make a async REST with Spring?

The response body is blank because the @Async annotation is used at findEmail method of UserRepository class, it means that there is no data returned to the following sentence User user = userRepository.findByEmail(email); because findByEmail method is running on other different thread and will return null instead of a List object.

The @Async annotation is enabled when you declare @EnableAsync that is the reason why it only happens when you use @EnableAsync because it activates the @Async of findEmail method to run it on other thread.

The method return userService.findByEmail(email); will return a CompletableFuture object that is created from UserService class.

The difference with the second method call is that thenApplyAsync method will create a totally new CompletableFuture from the previous one that comes from userService.findByEmail(email) and will only return the user object that comes from the first CompletableFuture.

 return userService.findByEmail(email).thenApplyAsync(user -> {
      return user;
    })

If you want to get the expected results just remove the @Async annotation from findByEmail method, and finally add the @EnableAsync Annotation

If you need to clarify ideas of how to use Async methods, lets say that you have to call three methods and each one takes 2 seconds to finish, in a normal scenario you will call them method1, then method2 and finally method3 in that case you entire request will take 6 seconds. When you activate the Async approach then you can call three of them and just wait for 2 seconds instead of 6.

Add this long method to user service:

@Async
public  CompletableFuture<Boolean> veryLongMethod()  {

    try {
        Thread.sleep(2000L);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    return CompletableFuture.completedFuture(true);
}

And call it three times from Controller, like this

  @RequestMapping(value = "test")
  public @ResponseBody CompletableFuture<User> test(@RequestParam(value = "email", required = true) String email) throws InterruptedException {
        CompletableFuture<Boolean> boolean1= siteService.veryLongMethod();
        CompletableFuture<Boolean> boolean2= siteService.veryLongMethod();
        CompletableFuture<Boolean> boolean3= siteService.veryLongMethod();

        CompletableFuture.allOf(boolean1,boolean2,boolean3).join();
    return userService.findByEmail(email);
  }  

Finally measure the time that takes your response, if it takes more than 6 seconds then you are not running Async method, if it takes only 2 seconds then you succeed.

Also see the following documentation: @Async Annotation, Spring async methods, CompletableFuture class

Hope it help.


The Asynchronous child threads start executing very late (around 20 to 30 seconds delay).

I'm using ThreadPoolTaskExecutor() in my main SpringBoot application class. You can also try the same if you consider performance as a factor.