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.

Leave a Comment

tech