Async API Call Using @Async Annotation In Spring Boot

async

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:

  1. Async Servlet Support: Spring MVC controllers can be annotated with @Async to handle requests asynchronously.
  2. Spring WebFlux: Built on top of Project Reactor, Spring WebFlux provides a reactive programming model for handling asynchronous requests using reactive streams.
  3. CompletableFuture and @Async Method: You can use Java’s CompletableFuture along with the @Async annotation on methods to perform asynchronous operations.
  4. 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 using RestTemplate.
  • 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 using CompletableFuture.get().
  • In the Application class, we define a bean named asyncExecutor of type AsyncTaskExecutor. We configure this bean as a ThreadPoolTaskExecutor 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.

Address

4232 Farnum Road, New York, New York(NY), 10029

Telephone: 212-289-5109

Mobile: 917-216-4839

Copyright © 2024 Learn Spring Boot Online