Open In App

Spring Boot – Handling Background Tasks with Spring Boot

Last Updated : 27 Aug, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

Efficiently handling background tasks with Spring Boot is important for providing a smooth user experience and optimizing resource utilization. Background tasks refer to operations that are performed asynchronously or in the background, allowing the main application to continue processing other requests. In a Spring Boot application, background tasks can be managed using several mechanisms, including @Async for simple asynchronous processing or @Scheduled for periodic tasks.

This article will guide you through setting up and managing background tasks in a Spring Boot application, using practical examples to illustrate the concepts.

Prerequisites

  • Basic knowledge of Java and Spring Boot.
  • Understanding of multithreading and asynchronous programming concepts.
  • Maven for dependency management.
  • JDK and IntelliJ IDEA installed in your system.

Handling background tasks efficiently is a crucial aspect of developing scalable and responsive applications. In Spring Boot, background tasks can be managed using several mechanisms, each suited to different types of tasks:

  • Asynchronous Methods with @Async: Allows methods to run in a separate thread, freeing up the main thread to handle other tasks.
  • Scheduled Tasks with @Scheduled: Enables periodic execution of tasks at fixed intervals or specified times.
  • Task Execution and Scheduling Configuration: Spring Boot allows you to configure thread pools and schedulers to manage these background tasks efficiently.

Implementation of Handling Background Tasks with Spring Boot

Step 1: Create a New Spring Boot Project

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

  • Name: spring-boot-background-tasks
  • Language: Java
  • Type: Maven
  • Packaging: Jar

Click on the Next button.

Project Metadata

Step 2: Add Dependencies

Add the following dependencies into the Spring Boot project.

Add Dependencies

Project Structure

Once the creation of the project completed, the file structure will look like the below image.

Project Folder Structure

Step 3: Application Properties

Set the application properties to define the application name and server port.

spring.application.name=spring-boot-background-tasks
server.port=8080

Step 4: Create the AsyncConfig Class

This configuration class defines the Executor bean used for asynchronous tasks.

Java
package com.gfg.springbootbackgroundtasks;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

@Configuration
public class AsyncConfig {

    @Bean(name = "taskExecutor")
    public Executor taskExecutor() {
        if (supportsVirtualThreads()) {
            // Configure for virtual threads if supported
            return Executors.newWorkStealingPool();
        } else {
            // Fall back to standard thread pool
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(5);
            executor.setMaxPoolSize(10);
            executor.setQueueCapacity(100);
            executor.setThreadNamePrefix("AsyncThread-");
            executor.initialize();
            return executor;
        }
    }

    private boolean supportsVirtualThreads() {
        // Example check for virtual threads support
        return System.getProperty("java.version").startsWith("19") || 
               System.getProperty("java.version").startsWith("20");
    }
}

The AsyncConfig class provides an Executor bean that is used to run asynchronous tasks. It checks if the Java version supports virtual threads and configures the executor accordingly.

Step 5: Create the AsyncService Class

This service class executes tasks asynchronously using the configured taskExecutor.

Java
package com.gfg.springbootbackgroundtasks;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class AsyncService {

    @Async("taskExecutor")
    public void executeAsyncTask() {
        System.out.println("Execute method asynchronously - " + Thread.currentThread().getName());
        try {
            // Simulating a long-running task
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Task execution completed");
    }
}
  • The AsyncService class contains a method annotated with @Async, which allows it to run in a separate thread using the taskExecutor.
  • It simulates a long-running task by sleeping for 5 seconds.

Step 6: Create the ScheduledTaskService Class

This service class runs scheduled tasks at a fixed rate within the Spring Boot application.

Java
package com.gfg.springbootbackgroundtasks;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

@Service
public class ScheduledTaskService {

    @Scheduled(fixedRate = 10000)
    public void performScheduledTask() {
        System.out.println("Scheduled task executed at " + System.currentTimeMillis());
    }
}

The ScheduledTaskService class has a method annotated with @Scheduled, which runs a task every 10 seconds, logging the current time to the console.

Step 7: Create the TaskController Class

This controller exposes an endpoint to trigger the asynchronous task.

Java
package com.gfg.springbootbackgroundtasks;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/tasks")
public class TaskController {

    @Autowired
    private AsyncService asyncService;

    @GetMapping("/run")
    public String runBackgroundTask() {
        asyncService.executeAsyncTask();
        return "Background task is running...";
    }
}
  • The TaskController class defines a REST API endpoint that triggers the asynchronous task in AsyncService.
  • When a GET request is made to /api/tasks/run, the background task starts running.

Step 8: Main class

Add the @EnableAsync annotation in the main class to enable asynchronous task support.

Java
package com.gfg.springbootbackgroundtasks;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication
@EnableAsync
public class SpringBootBackgroundTasksApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootBackgroundTasksApplication.class, args);
    }

}
  • The main class, SpringBootBackgroundTasksApplication, is the entry point of the application.
  • The @EnableAsync annotation is added to enable asynchronous processing within the application.

pom.xml file:

XML
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.gfg</groupId>
    <artifactId>spring-boot-background-tasks</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot-background-tasks</name>
    <description>spring-boot-background-tasks</description>
    <url/>
    <licenses>
        <license/>
    </licenses>
    <developers>
        <developer/>
    </developers>
    <scm>
        <connection/>
        <developerConnection/>
        <tag/>
        <url/>
    </scm>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

Step 9: Run the application

Once the project is completed, run the application. It will start on port 8080.

Application Started

Step 10: Run the Background Tasks using Endpoint

Make a GET request to the following endpoint to trigger the asynchronous task:

GET http://localhost:8080/api/tasks/run

The asynchronous task will start running in the background, allowing the HTTP request to return immediately with the message "Background task is running...".

Message Returns

Output:

The background tasks progress and completion will be printed in the console output.

Console Output

This example project demonstrates a simple way to run background tasks using Spring Boot's asynchronous capabilities. You can expand this by handling different types of tasks, improving error handling, or adding monitoring and logging for production use.


Next Article

Similar Reads