Using CompletableFuture with Async Methods in Spring Boot

In modern application development, responsiveness and scalability are key. One way to achieve this is by leveraging asynchronous programming. In Java, CompletableFuture combined with Spring’s @Async provides a powerful way to write non-blocking, concurrent code. This post explores using CompletableFuture with async methods in a Spring Boot application.

Using CompletableFuture with Async Methods in Spring Boot

🚀 Why Use CompletableFuture?

The CompletableFuture class, introduced in Java 8, represents a future result of an asynchronous computation. Unlike Future, it allows non-blocking operations and supports chaining multiple tasks.

With Spring Boot, we can annotate methods with @Async to run them in a separate thread. When used with CompletableFuture, we get a fluent, readable, and efficient way to perform async operations.

⚙️ Maven Dependencies

Make sure your project uses Spring Boot with Spring Context. Here’s your pom.xml dependency:

🛠️ Enable Async Support

In your main Spring Boot class or configuration class:

📦 Sample Service with CompletableFuture and @Async

Let’s create a service to simulate a long-running task using CompletableFuture with async methods.

🎯 Controller to Trigger Async Operations

Here’s a simple controller that invokes both async methods and combines the results using thenCombine.

🧪 Output

When you hit the /combine-data endpoint, both async methods will run in parallel and the combined result will be returned once both complete.

Example Output:

Execution time: ~3 seconds instead of 5 seconds, thanks to async parallelism.

⚠️ Notes and Best Practices

  1. @EnableAsync must be present to enable async behavior.
  2. @Async methods should return CompletableFuture for proper async chaining.
  3. Exception handling is tricky—wrap logic in .handle() or use .exceptionally().
  4. Async methods must not be private, and should be called via a Spring-managed bean (i.e., no this.method()).

📌 Use Case: API Aggregation

Using CompletableFuture with async methods is ideal for:

  • Fetching data from multiple APIs simultaneously.
  • Processing large datasets in parallel.
  • Background jobs or deferred processing tasks.

🧹 Cleaning Up with Custom Executor

By default, Spring uses SimpleAsyncTaskExecutor. You can define your own thread pool:

Then in your service:

🧾 Conclusion

Combining CompletableFuture with async methods is a powerful technique to make your Spring Boot applications scalable and performant. By understanding and leveraging this pattern, you can drastically reduce latency in I/O-bound applications.

✅ You’ve now learned how to effectively use CompletableFuture with async methods in Spring Boot.

✅ Summary

  • ✅ Use @Async on service methods.
  • ✅ Return CompletableFuture for non-blocking processing.
  • ✅ Combine futures using .thenCombine, .thenApply, .exceptionally, etc.
  • ✅ Customize thread pools for better resource management.