Ebooks

Spring Boot scheduling tasks

Spring Boot scheduling tasks tutorial shows how to schedule tasks with @Scheduled in a Spring Boot application.

Spring Boot is a popular framework for building enterprise applications in Java, Kotlin, or Groovy.

Spring Boot scheduling tasks

The @EnableScheduling enables scheduling in a Spring Boot application. Methods decorated with the @Scheduled annotation are run periodically. The methods should return void and should not have any parameters.

The ScheduledAnnotationBeanPostProcessor is a bean post-processor that registers methods annotated with @Scheduled to be invoked by a TaskScheduler according to the fixedRate, fixedDelay, cron expression provided via the annotation. The fixedDelay property runs tasks with a fixe delay of n millisecond between consecutive executions of tasks. The fixedRate runs the scheduled task at every n millisecond. It does not check for any previous executions of the task.

The @Scheduled(cron="pattern") allows to define a crontab pattern to run tasks. The pattern is a list of six single space-separated fields: representing second, minute, hour, day, month, weekday. Month and weekday names can be given as the first three letters of the English names. For instance, the "0 0/30 8-10 * * *" cron pattern schedules tasks to be run at 8:00, 8:30, 9:00, 9:30, 10:00 and 10:30 every day.

Spring Boot scheduling example

In the following application, we schedule a task with a fixed rate of 15s. The task connects to a website and reads its date header.

pom.xml
src
├───main
│   ├───java
│   │   └───com
│   │       └───zetcode
│   │           │   Application.java
│   │           ├───scheduling
│   │           │       ScheduledTasks.java
│   │           └───service
│   │                   HeadRequestService.java
│   └───resources
│           application.properties
└───test
    └───java

This is the project structure of the Spring Boot application.

pom.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
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zetcode</groupId>
    <artifactId>SpringBootSchedule</artifactId>
    <version>1.0-SNAPSHOT</version>

    <packaging>jar</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
    </parent>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

This is the Maveb build file. We add the spring-boot-starter-web for a simple web application.

resources/application.properties
spring.main.banner-mode=off
spring.main.log-startup-info=false

The application.properties file contains application configuration settings. With the spring.main.banner-mode, we turn off the Spring Boot banner and with the spring.main.log-startup-info property, we turn off the startup logging information.

com/zetcode/scheduling/ScheduledTasks.java
package com.zetcode.scheduling;

import com.zetcode.service.HeadRequestService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ScheduledTasks {

    @Autowired
    private HeadRequestService headRequestService;

    private static final Logger log = LoggerFactory.getLogger(ScheduledTasks.class);

    @Scheduled(fixedRate = 15000)
    public void getHeadValue() {
        log.info("Value: {}", headRequestService.doHeadRequest());
    }
}

In the ScheduledTasks, we schedule a task to run every 15s.

@Scheduled(fixedRate = 15000)
public void getHeadValue() {
    log.info("Value: {}", headRequestService.doHeadRequest());
}

Every 15s, the doHeadRequest() of the HeadRequestService is called.

com/zetcode/service/HeadRequestService.java
package com.zetcode.service;

import com.zetcode.scheduling.ScheduledTasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpHeaders;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

@Service
public class HeadRequestService {

    private static final Logger log = LoggerFactory.getLogger(ScheduledTasks.class);
    private HttpHeaders headers;

    public String doHeadRequest() {

        HttpClient client = HttpClient.newHttpClient();

        try {
            var request = HttpRequest.newBuilder(URI.create("http://webcode.me"))
                    .method("HEAD", HttpRequest.BodyPublishers.noBody())
                    .build();

            HttpResponse<Void> response = client.send(request,
                    HttpResponse.BodyHandlers.discarding());

            headers = response.headers();

        } catch (IOException | InterruptedException e) {

            log.error("Failed to send HEAD request");
        }

        var opt = headers.firstValue("date");
        return opt.orElse("");
    }
}

The doHeadRequest() method issues a HEAD request to the webcode.me website and retrieves the date header from its response.

com/zetcode/Application.java
package com.zetcode;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.MediaType;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@EnableScheduling
@RestController
public class Application {

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

    @GetMapping(value = "/", produces = MediaType.TEXT_PLAIN_VALUE)
    private String home() {

        return "home page";
    }
}

In the Applicaiton, we set up the Spring Boot application. With the @EnableScheduling, we enable scheduling for the application. In addition, we add a simple web page that returns text.

$ mvn -q spring-boot:run
...
2020-01-22 14:32:46.121  INFO 18188 --- [   scheduling-1] com.zetcode.scheduling.ScheduledTasks    : Value: Wed, 22 Jan 2020 13:33:51 GMT
2020-01-22 14:33:00.881  INFO 18188 --- [   scheduling-1] com.zetcode.scheduling.ScheduledTasks    : Value: Wed, 22 Jan 2020 13:34:06 GMT
2020-01-22 14:33:15.904  INFO 18188 --- [   scheduling-1] com.zetcode.scheduling.ScheduledTasks    : Value: Wed, 22 Jan 2020 13:34:21 GMT

We run the application with mvn -q spring-boot:run. In the output we can see the messages of the scheduled method.

In this tutorial, we have worked with scheduling in a Spring Boot applicaiton.

List Spring Boot tutorials.