Table of Contents
Introduction
In Spring Boot, an async call refers to making a non-blocking, asynchronous request to a resource, such as an external API, database, or another service. This allows your application to continue executing other tasks while waiting for the response from the external resource.
Spring Boot provides several mechanisms to achieve asynchronous behavior:
- Async Servlet Support: Spring MVC controllers can be annotated with
@Async
to handle requests asynchronously. - Spring WebFlux: Built on top of Project Reactor, Spring WebFlux provides a reactive programming model for handling asynchronous requests using reactive streams.
- CompletableFuture and @Async Method: You can use Java’s CompletableFuture along with the
@Async
annotation on methods to perform asynchronous operations. - Reactive WebClient: Spring’s
WebClient
supports reactive programming and can be used to make asynchronous HTTP requests.
Async calls in Spring Boot are beneficial for improving application performance and responsiveness, especially in scenarios where there are long-running tasks or external dependencies. By making calls asynchronously, your application can handle more requests concurrently and utilize resources efficiently.
Add Dependency
First, make sure you have the necessary dependencies in your pom.xml
(if using Maven) or build.gradle
(if using Gradle):
For Maven:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
For Gradle:
implementation 'org.springframework.boot:spring-boot-starter-web'
Implementation For Async Processing
In Spring Boot, you can make asynchronous API calls using Spring’s RestTemplate
in combination with Java’s CompletableFuture
. Here’s a brief example:
Define AsyncService
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.concurrent.CompletableFuture;
@Service
public class LearnSpringBootOnlineAsyncService {
private final RestTemplate restTemplate;
public LearnSpringBootOnlineAsyncService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@Async
public CompletableFuture<String> asyncAPICall() {
String apiUrl = "https://learnspringbootonline.com"; // Replace with your API URL
String result = restTemplate.getForObject(apiUrl, String.class);
return CompletableFuture.completedFuture(result);
}
}
Configuration and Main Class
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableAsync
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
Configure Thread Pool
To configure thread pool size and other properties for asynchronous calls in Spring Boot, you can customize the TaskExecutor
bean. Here’s how you can modify the previous example to include configuration for thread pool size:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableAsync
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean(name = "asyncExecutor")
public AsyncTaskExecutor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5); // Set your desired core pool size
executor.setMaxPoolSize(10); // Set your desired maximum pool size
executor.setQueueCapacity(100); // Set your desired queue capacity
executor.setThreadNamePrefix("AsyncThread-");
executor.initialize();
return executor;
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
In this example:
- LearnSpringBootOnlineAsyncService class defines a method
asyncAPICall()
annotated with@Async
. This method performs the asynchronous API call usingRestTemplate
. Application
class is the main class annotated with@SpringBootApplication
and@EnableAsync
to enable asynchronous processing.AsyncController
class defines a REST endpoint/async-api
that triggers the asynchronous API call. The method blocks and waits for the result usingCompletableFuture.get()
.- In the
Application
class, we define a bean namedasyncExecutor
of typeAsyncTaskExecutor
. We configure this bean as aThreadPoolTaskExecutor
and set properties such as core pool size, maximum pool size, and queue capacity. - Note: Make sure to configure
RestTemplate
bean in your application context, as shown in the main class.
With this configuration, Spring Boot will use the customized thread pool for executing asynchronous tasks, allowing you to control the concurrency and manage resources effectively. Adjust the core pool size, maximum pool size, and queue capacity according to your application’s requirements.
Conclusion
In conclusion, the provided asynchronous implementation in Spring Boot allows for efficient handling of API calls by leveraging the @Async
annotation and customizing the thread pool configuration.
By annotating the appropriate methods with @Async
, we enable non-blocking execution of tasks, ensuring that the application remains responsive and can handle multiple requests concurrently. Additionally, the custom configuration of the thread pool through the ThreadPoolTaskExecutor
bean allows us to fine-tune parameters such as core pool size, maximum pool size, and queue capacity to optimize resource utilization and manage concurrency effectively.
Overall, this approach enhances the scalability and performance of the application, enabling it to handle a higher volume of requests while maintaining responsiveness and efficient resource utilization.
Explore our diverse collection of blogs covering a wide range of topics here.