How to make a async REST with Spring?

Viewed 56326

I'm trying to make a small REST using Spring Boot. I've never used Spring and used Java a long time ago (Java 7)!

In the last 2 years I have used only Python and C# (but like I said, I already used Java).

So, now, I'm trying to make a REST using async methods, and checked several examples, but still, I don't understand very well the "correct way" to do this.

Looking at the following documentation: http://carlmartensen.com/completablefuture-deferredresult-async, Java 8 has CompletableFuture that I can use with Spring, so, I made the following code:

Service:

@Service
public class UserService {
  private UserRepository userRepository;

  // dependency injection
  // don't need Autowire here
  // https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-spring-beans-and-dependency-injection.html
  public UserService(UserRepository userRepository) {
    this.userRepository = userRepository;
  }

  @Async
  public CompletableFuture<User> findByEmail(String email) throws InterrupedException {
    User user = userRepository.findByEmail(email);
    return CompletableFuture.completedFuture(user);
  }
}

Repository:

public interface UserRepository extends MongoRepository<User, String> {
  @Async
  findByEmail(String email);
}

RestController:

@RestController
public class TestController {

  private UserService userService;

  public TestController(UserService userService) {
    this.userService = userService;
  }

  @RequestMapping(value = "test")
  public @ResponseBody CompletableFuture<User> test(@RequestParam(value = "email", required = true) String email) throws InterruptedException {
    return userService.findByEmail(email).thenApplyAsync(user -> {
      return user;
    })
  }  
}

This code give me the expected output. Then, looking at another documentation (sorry, I lost the link), I see that Spring accept the following code (which give me the expected output too):

  @RequestMapping(value = "test")
  public @ResponseBody CompletableFuture<User> test(@RequestParam(value = "email", required = true) String email) throws InterruptedException {
    return userService.findByEmail(email);
  }  
}

Is there a difference between the two methods?

Then, looking at the following guide: https://spring.io/guides/gs/async-method/, there's a @EnableAsync annotation in SpringBootApplication class. If I include the @EnableAsync annotation and create a asyncExecutor Bean like the code from last link, my application don't return nothing on /test endpoint (only a 200 OK response, but with blank body).

So, my rest is async without the @EnableAsync annotation? And why when I use @EnableAsync, the response body is blank?

2 Answers
Related