Skip to content
geeksforgeeks
  • Courses
    • DSA to Development
    • Get IBM Certification
    • Newly Launched!
      • Master Django Framework
      • Become AWS Certified
    • For Working Professionals
      • Interview 101: DSA & System Design
      • Data Science Training Program
      • JAVA Backend Development (Live)
      • DevOps Engineering (LIVE)
      • Data Structures & Algorithms in Python
    • For Students
      • Placement Preparation Course
      • Data Science (Live)
      • Data Structure & Algorithm-Self Paced (C++/JAVA)
      • Master Competitive Programming (Live)
      • Full Stack Development with React & Node JS (Live)
    • Full Stack Development
    • Data Science Program
    • All Courses
  • Tutorials
    • Data Structures & Algorithms
    • ML & Data Science
    • Interview Corner
    • Programming Languages
    • Web Development
    • CS Subjects
    • DevOps And Linux
    • School Learning
  • Practice
    • Build your AI Agent
    • GfG 160
    • Problem of the Day
    • Practice Coding Problems
    • GfG SDE Sheet
  • Contests
    • Accenture Hackathon (Ending Soon!)
    • GfG Weekly [Rated Contest]
    • Job-A-Thon Hiring Challenge
    • All Contests and Events
  • Java Tutorial
  • Java Spring
  • Spring Interview Questions
  • Java SpringBoot
  • Spring Boot Interview Questions
  • Spring MVC
  • Spring MVC Interview Questions
  • Java Hibernate
  • Hibernate Interview Questions
  • Advance Java Projects
  • Java Interview Questions
Open In App
Next Article:
Implementing Secure API Communication in Spring Boot
Next article icon

Spring MVC – Implementing Asynchronous Request Processing

Last Updated : 19 Sep, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

In Spring MVC, asynchronous request processing allows the server to handle requests in a non-blocking manner. This approach improves performance by freeing up resources while waiting for responses, which is especially useful for long-running tasks such as remote service calls, file processing, or database queries. Asynchronous processing can enhance server scalability and responsiveness in high-traffic applications.

Implementing Asynchronous Request Processing in Spring MVC

Asynchronous processing in Spring MVC involves handling requests using separate threads, allowing the main thread to continue processing other requests. Key components for asynchronous processing in Spring MVC include DeferredResult, Callable, and WebAsyncTask.

Key Terminologies:

  • @Async: A Spring annotation used to mark a method for asynchronous execution. Methods annotated with @Async are executed asynchronously in a separate thread, allowing the main thread to continue processing other tasks.
  • Callable: An interface in Java that represents a task that can be executed asynchronously. In Spring MVC, a method returning a Callable allows asynchronous request handling.
  • DeferredResult: A flexible class that allows the server to return a result later, after a delay. It is often used in event-driven applications where the completion of the task depends on external events or processes.
  • WebAsyncTask: A class that extends Callable and provides more control over asynchronous tasks, including timeouts, custom thread pools, and task cancellation.

DeferredResult

DeferredResult in Spring MVC is an abstraction for returning the result of a long-running request without blocking the main processing thread. It decouples the request handling from the actual response, which is provided asynchronously once an event (like a background task or external service call) completes.

When to Use DeferredResult?

Use DeferredResult when the response depends on multiple asynchronous events, and you want to return the result only when these events are completed.

Example Usage:

@RestController
public class DeferredResultController {

@Autowired
private LongRunningService longRunningService;

@GetMapping("/async-deferred")
public DeferredResult<String> handleDeferredResult() {
DeferredResult<String> deferredResult = new DeferredResult<>();

// Simulate asynchronous task using a separate thread
new Thread(() -> {
try {
String result = longRunningService.process();
deferredResult.setResult(result);
} catch (InterruptedException e) {
deferredResult.setErrorResult("Error occurred while processing.");
}
}).start();

return deferredResult;
}
}

Key Features of DeferredResult:

  • The main thread is not blocked while processing the request.
  • Results can be set manually using setResult(), and errors can be handled using setErrorResult().
  • Supports timeouts to handle cases where the response takes too long.

WebAsyncTask

WebAsyncTask is another way to handle asynchronous requests in Spring MVC. It extends Callable and offers more control, including timeouts, error handling, and custom thread pools.

When to Use WebAsyncTask?

Use WebAsyncTask when you need more control over timeouts, error handling, or want to execute tasks in different thread pools.

Example Usage:

@RestController
public class WebAsyncTaskController {

@Autowired
private LongRunningService longRunningService;

@GetMapping("/async-webasynctask")
public WebAsyncTask<String> handleWebAsyncTask() {
Callable<String> callableTask = () -> longRunningService.process();

// Create WebAsyncTask with a timeout and Callable task
WebAsyncTask<String> webAsyncTask = new WebAsyncTask<>(6000, callableTask);

// Handle timeout
webAsyncTask.onTimeout(() -> "Task timed out!");

// Handle error
webAsyncTask.onError(() -> "Error occurred while processing the task!");

return webAsyncTask;
}
}

Key Features of WebAsyncTask:

  • Allows setting timeouts for long-running tasks.
  • Supports error handling and fallback responses.
  • Provides better control over thread pools and task management compared to Callable.

Callable

Callable is a simple way to execute long-running tasks asynchronously. When a Callable is returned from a controller method, Spring processes it in a separate thread and sends the result back when the task completes.

When to Use Callable?

Use Callable for straightforward asynchronous tasks where the result is returned after a single task completes, and advanced error or timeout handling is not required.

Example Usage:

@RestController
public class CallableController {

@Autowired
private LongRunningService longRunningService;

@GetMapping("/async-callable")
public Callable<String> handleCallable() {
// Return a Callable that simulates a long-running task
return () -> longRunningService.process();
}
}

Key Features of Callable:

  • Simplifies execution of asynchronous tasks.
  • Automatically returns the result once the Callable completes.
  • No complex configuration is needed, making it ideal for simple use cases.

@Async and Thread Pool Configuration

@Async

@Async is a Spring annotation that allows methods to be executed asynchronously in a separate thread. This enables background processing without holding up the main thread.

When to Use @Async?

Use @Async for tasks that can be executed in the background, such as sending emails, making external API calls, or processing large datasets.

Example Usage:

@Service
public class AsyncService {

@Async
public void executeAsyncTask() throws InterruptedException {
Thread.sleep(5000); // Simulate a long-running task
System.out.println("Async task completed.");
}
}

Thread Pool Configuration for @Async

By default, @Async methods use Spring's simple thread pool executor. For better control, you can configure a custom thread pool to define the number of concurrent threads, maximum threads, queue capacity, and more.

Java Configuration for Custom Thread Pool:

@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {

@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5); // Minimum number of threads in the pool
executor.setMaxPoolSize(10); // Maximum number of threads
executor.setQueueCapacity(100); // Queue size before rejecting new tasks
executor.setThreadNamePrefix("AsyncTask-");
executor.initialize();
return executor;
}
}

Thread Pool Configuration via application.properties:

# Spring asynchronous configuration
spring.task.execution.pool.core-size=5
spring.task.execution.pool.max-size=10
spring.task.execution.pool.queue-capacity=100
spring.task.execution.thread-name-prefix=async-task-

Configuration Details:

  • core-size: Defines the minimum number of threads the pool maintains.
  • max-size: The maximum number of threads allowed.
  • queue-capacity: Defines the size of the queue for holding tasks before rejecting them.
  • thread-name-prefix: Sets the prefix for thread names.

Workflow

  1. The client sends a request.
  2. The server delegates the request to the asynchronous thread pool.
  3. The server returns immediately, without blocking the main thread.
  4. Once the task is complete, the result is returned to the client.

Implementing Asynchronous Request Processing in Spring MVC

Step 1: Create a New Spring Boot Project

Create a new Spring Boot project using IntelliJ IDEA with the following options:

  • Name: spring-async-example
  • Language: Java
  • Type: Maven
  • Packaging: Jar

Click on the Next button.

Project Metadata

Step 2: Add Dependencies

We can add the following dependencies into the Spring Boot Project.

  • Spring Web
  • Lombok
  • Spring Boot DevTools

Click on the Create button.

Add Dependencies

Project Structure

After project creation done successfully, the folder structure will look like the below image:

Project Folder Structure

Step 3: Configure Application Properties

In the application.properties file, configure asynchronous request timeout and thread pool settings:

spring.application.name=spring-async-example

# Asynchronous request timeout
spring.mvc.async.request-timeout=60000

# Thread pool configuration for async tasks
spring.task.execution.pool.core-size=5
spring.task.execution.pool.max-size=10
spring.task.execution.pool.queue-capacity=100
spring.task.execution.thread-name-prefix=async-task-

Step 4: Create the LongRunningService Class

Create a service class that simulates a long-running task.

LongRunningService.java:

Java
package com.gfg.springasyncexample;  import org.springframework.stereotype.Service;  @Service public class LongRunningService {      public String process() throws InterruptedException {         // Simulate a time-consuming process (e.g., database call, API call)         Thread.sleep(5000);  // Simulate delay         return "Task completed successfully!";     } } 

Step 5: Create the CallableController Class

Create the CallableController class and this class can be useful when you have the single long-running task that you want to handle the asynchronously. It automatically returns the result once the task is done.

CallableController.java:

Java
package com.gfg.springasyncexample;  import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;  import java.util.concurrent.Callable;  @RestController public class CallableController {      @Autowired     private LongRunningService longRunningService;      @GetMapping("/async-callable")     public Callable<String> handleCallable() {         // Return a Callable that simulates a long-running task         return () -> longRunningService.process();     } } 

Step 6: Create the DeferredResultController Class

Create the DeferredResultController class and this class is ideal for handling cases where the response might depend on the multiple asynchronous events or when you need the external events to the trigger the response.

DeferredResultController.java:

Java
package com.gfg.springasyncexample;  import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.request.async.DeferredResult;  @RestController public class DeferredResultController {      @Autowired     private LongRunningService longRunningService;      @GetMapping("/async-deferred")     public DeferredResult<String> handleDeferredResult() {         DeferredResult<String> deferredResult = new DeferredResult<>();          // Simulate asynchronous task using a separate thread         new Thread(() -> {             try {                 String result = longRunningService.process();                 deferredResult.setResult(result);             } catch (InterruptedException e) {                 deferredResult.setErrorResult("Error occurred while processing.");             }         }).start();          return deferredResult;     } } 

Step 7: Create the WebAsyncTask Class

Create the WebAsyncTask class. WebAsyncTask provides the more control over the execution of the task. It allows us to define the timeouts, thread pools, and handle the errors more gracefully.

WebAsyncTaskController.java:

Java
package com.gfg.springasyncexample;  import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.request.async.WebAsyncTask;  import java.util.concurrent.Callable;  @RestController public class WebAsyncTaskController {      @Autowired     private LongRunningService longRunningService;      @GetMapping("/async-webasynctask")     public WebAsyncTask<String> handleWebAsyncTask() {         Callable<String> callableTask = () -> longRunningService.process();          // Create WebAsyncTask with a timeout and Callable task         WebAsyncTask<String> webAsyncTask = new WebAsyncTask<>(6000, callableTask);          // Handle timeout         webAsyncTask.onTimeout(() -> "Task timed out!");          // Handle error         webAsyncTask.onError(() -> "Error occurred while processing the task!");          return webAsyncTask;     } } 

Step 8: Main Application

This is entry point for the Spring Boot application, add the @Async anntotation to enable the asynchronous functionalities in this project.

Java
package com.gfg.springasyncexample;  import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableAsync;  @SpringBootApplication @EnableAsync public class SpringAsyncExampleApplication {      public static void main(String[] args) {         SpringApplication.run(SpringAsyncExampleApplication.class, args);     }  } 

Step 9: Run the Application

Now run the application, and it will start at port 8080.

Application Runs

Step 10: Testing the Application

We can test the application using postman tool.

1. Callable Output:

After calling /async-callable, we will see the message after a 5-second delay:

GET http://localhost:8080/async-callable

Response:

Callable Output

2. DeferredResult Output:

After calling /async-deferred, we will see the message after a 5-second delay:

GET http://localhost:8080/async-deferred

Response:

DeferredResult Output


3. WebAsyncTask Output:

After calling /async-webasynctask, we will either see

Task completed successfully!

or, if the task exceeds the timeout limit:

Task timeout occurred!

Response:

WebAsyncTask Output

The example project demonstrates the asynchronous request processing scenario, demonstrating how to delay the response to the client while handling background tasks. It can be critical in modern web applications where the server needs to handle the multiple requests without being blocked by long-running processes.


Next Article
Implementing Secure API Communication in Spring Boot

M

maheshkoced
Improve
Article Tags :
  • Advance Java
  • Java-Spring-MVC

Similar Reads

  • Asynchronous Processing in System Design
    Asynchronous processing involves handling tasks independently of the main program flow. It allows systems to execute multiple tasks concurrently, improving efficiency and responsiveness. This method is especially beneficial for waiting operations, such as I/O tasks or network requests. In this artic
    10 min read
  • Implementing Round Robin Load Balancing in Spring Boot Microservices
    Round Robin Load Balancing is a method of distributing client requests across multiple servers in a sequential manner. It ensures that each server handles an equal number of requests over time. This approach can be particularly useful for evenly distributing the load and avoiding overburdening a sin
    7 min read
  • Implementing Rate Limiting in a Spring Boot Application
    Rate limiting is a crucial feature in many web applications to control the amount of incoming and outgoing traffic. By implementing rate limiting, you can prevent server overload, ensure fair usage, and protect against abuse, such as Denial of Service (DoS) attacks. In a Spring Boot application, rat
    5 min read
  • Implementing Secure API Communication in Spring Boot
    In modern web applications, securing API communication is important to protect sensitive data and ensuring the integrity of interactions between clients and servers. In this article, we will learn how to implement secure API communication in a Spring Boot application. Securing API communication is c
    5 min read
  • Implementing Request Response in Java Apache Kafka
    Apache Kafka is a very powerful distributed event streaming platform that can be used for building real-time pipelines and streaming applications. It is highly scalable, fault-tolerant, and provides high throughput. One of the common patterns used in the Kafka application is the request-response pat
    6 min read
  • Spring MVC - @RequestParam Annotation
    The @RequestParam annotation is one of the most commonly used annotations in Spring MVC for handling HTTP request parameters. @RequestParam annotation enables Spring to extract input data that may be passed as a query, form data, or any arbitrary custom data. Key features of @RequestParam annotation
    5 min read
  • Spring MVC - Getting Cryptocurrency Details using REST API
    Cryptocurrencies are a hot topic throughout the world. Trading with cryptocurrency got both pros and cons. Nowadays REST APIs are very useful to get much information including cryptocurrencies. In this article, we are going to see about one such REST API call to get cryptocurrency detail. We are goi
    5 min read
  • Spring MVC @SessionAttributes Annotation with Example
    In the ever-evolving world of web development, a constant challenge is to seamlessly manage data between requests. Enter Spring MVC's @SessionAttributes annotation, a powerful solution that elegantly manages the session attributes of a Spring application. This markup becomes a lifesaver when certain
    3 min read
  • Modify Request Body Before Reaching Controller in Spring Boot
    In Spring Boot applications, efficiently handling HTTP requests is crucial, especially when it comes to modifying or validating the data before it reaches the controller. This might involve tasks such as formatting, logging, adding metadata, or sanitizing input. This article explores how to modify t
    6 min read
  • Spring Boot - Consuming and Producing JSON
    Spring Boot is one of the famous frameworks for developing web applications and this framework provides a lot of features like auto-configuration, Spring Integration, Dependency management, and other features are available in Spring Boot framework. In this article, we will explain Spring Boot Consum
    3 min read
geeksforgeeks-footer-logo
Corporate & Communications Address:
A-143, 7th Floor, Sovereign Corporate Tower, Sector- 136, Noida, Uttar Pradesh (201305)
Registered Address:
K 061, Tower K, Gulshan Vivante Apartment, Sector 137, Noida, Gautam Buddh Nagar, Uttar Pradesh, 201305
GFG App on Play Store GFG App on App Store
Advertise with us
  • Company
  • About Us
  • Legal
  • Privacy Policy
  • In Media
  • Contact Us
  • Advertise with us
  • GFG Corporate Solution
  • Placement Training Program
  • Languages
  • Python
  • Java
  • C++
  • PHP
  • GoLang
  • SQL
  • R Language
  • Android Tutorial
  • Tutorials Archive
  • DSA
  • Data Structures
  • Algorithms
  • DSA for Beginners
  • Basic DSA Problems
  • DSA Roadmap
  • Top 100 DSA Interview Problems
  • DSA Roadmap by Sandeep Jain
  • All Cheat Sheets
  • Data Science & ML
  • Data Science With Python
  • Data Science For Beginner
  • Machine Learning
  • ML Maths
  • Data Visualisation
  • Pandas
  • NumPy
  • NLP
  • Deep Learning
  • Web Technologies
  • HTML
  • CSS
  • JavaScript
  • TypeScript
  • ReactJS
  • NextJS
  • Bootstrap
  • Web Design
  • Python Tutorial
  • Python Programming Examples
  • Python Projects
  • Python Tkinter
  • Python Web Scraping
  • OpenCV Tutorial
  • Python Interview Question
  • Django
  • Computer Science
  • Operating Systems
  • Computer Network
  • Database Management System
  • Software Engineering
  • Digital Logic Design
  • Engineering Maths
  • Software Development
  • Software Testing
  • DevOps
  • Git
  • Linux
  • AWS
  • Docker
  • Kubernetes
  • Azure
  • GCP
  • DevOps Roadmap
  • System Design
  • High Level Design
  • Low Level Design
  • UML Diagrams
  • Interview Guide
  • Design Patterns
  • OOAD
  • System Design Bootcamp
  • Interview Questions
  • Inteview Preparation
  • Competitive Programming
  • Top DS or Algo for CP
  • Company-Wise Recruitment Process
  • Company-Wise Preparation
  • Aptitude Preparation
  • Puzzles
  • School Subjects
  • Mathematics
  • Physics
  • Chemistry
  • Biology
  • Social Science
  • English Grammar
  • Commerce
  • World GK
  • GeeksforGeeks Videos
  • DSA
  • Python
  • Java
  • C++
  • Web Development
  • Data Science
  • CS Subjects
@GeeksforGeeks, Sanchhaya Education Private Limited, All rights reserved
We use cookies to ensure you have the best browsing experience on our website. By using our site, you acknowledge that you have read and understood our Cookie Policy & Privacy Policy
Lightbox
Improvement
Suggest Changes
Help us improve. Share your suggestions to enhance the article. Contribute your expertise and make a difference in the GeeksforGeeks portal.
geeksforgeeks-suggest-icon
Create Improvement
Enhance the article with your expertise. Contribute to the GeeksforGeeks community and help create better learning resources for all.
geeksforgeeks-improvement-icon
Suggest Changes
min 4 words, max Words Limit:1000

Thank You!

Your suggestions are valuable to us.

What kind of Experience do you want to share?

Interview Experiences
Admission Experiences
Career Journeys
Work Experiences
Campus Experiences
Competitive Exam Experiences