Overview
Task scheduling refers to executing a task on a particular time frame or repeating the task by running a process in a fixed interval. Spring boot provides @Scheduled
and @EnableScheduling
annotations for configuring and scheduling tasks, periodically. Spring allows us to configure the parameters of the @Scheduled annotation by scheduling a task on a fixed rate, with a fixed delay, custom intervals, etc. In this article, we will discuss how to schedule tasks in a Spring boot application.
The thumb rule that needs to be followed to annotate a method with @Scheduled is that the method should not expect any parameters and must have void return type.
Project Setup for enabling scheduling in a Spring boot application
We can create the skeleton of our Spring boot project by using Spring Test Suite(STS), as usual. Creating a scheduler with Spring boot is straight forward. We need to add the @Scheduled
annotation to any method that runs automatically and include @EnableScheduling
to one of our @Configuration
classes. We do not need any additional dependencies to enable scheduling.
To enable scheduling, all we have to do, is annotate our main class:
@SpringBootApplication @EnableScheduling public class DemoScheduleApp { public static void main(String[] args) { SpringApplication.run(DemoScheduleApp.class, args); } }
Scheduling tasks
We can schedule Spring boot tasks by using @Scheduled annotation provided by Spring. But, based on the configuration of `fixedRate` and `fixedDelay` properties, the nature of execution of the tasks changes. Now, let’s configure the parameters of the @Scheduled annotation to schedule the time at which a task will run.
Scheduling a task with a fixed rate
The main job of a scheduler is to schedule the tasks. Spring Boot makes it easy to schedule a task by annotating a method with the @Scheduled annotation. We can schedule a method to be triggered at a fixed time interval by using fixedRate
parameter of the @Scheduled annotation. The fixedRate parameter accepts integers, specified in milliseconds.
This type of scheduling must be triggered when the execution of each task is independent. In the below example, the fixedRate property triggers the scheduled task to run at every at a fixed interval of 5 seconds.
@Scheduled(fixedRate = 5000) public void scheduleTaskFixedRate() { logger.info("Fixed Rate Task : The task execution time is : " + Calendar.getInstance().getTime()); }
Hence, the fixedRate property configures to run a scheduled task at every fixed interval. The fixedRate task is invoked at the fixed interval, even if the previous invocation of the task is not completed.
Scheduling a Task with Fixed Delay
We can schedule a task with a fixed delay between the completion of the last invocation of the task and the start invocation of the next task. This can be done by configuring fixedDelay
parameter of the @Scheduled annotation. In this case, the task always waits for the previous task to get completed. This type of scheduling is used for dependent tasks, where only one instance of the scheduled task runs all the time. For example, let’s schedule a task to run with a fixed delay:
@Scheduled(fixedDelay = 10000) public void scheduleTaskFixedDelay() { logger.info("Fixed Delay Task : The task execution time is", Calendar.getInstance().getTime()); try { TimeUnit.sleep(50000); } catch (InterruptedException ex) { logger.error("Unexpected error {}", ex); throw new IllegalStateException(ex); } }
Here, we have configured a task to run after a fixed delay. In given example, the duration between the end of last execution and the start of next execution is fixed. The task always waits until the previous one is finished. In the above example, the task gets completed at 5 seconds and since we have specified a delay of 10 seconds, the tasks are triggered with a total delay of 15 seconds. Hence, the fixedDelay configuration makes sure to create a delay of n milliseconds between the completion of an execution of task and the start invocation of the next task.
Scheduling a task with Initial Delay
We can configure the `initialDelay` parameter to delay the first execution of a scheduled task with a specified timeframe(specified in milliseconds). We can club this parameter with `fixedRate` and `fixedDelay` according to our requirements. For example, let’s trigger a task that runs every second, by waiting for 2 seconds before it executes for the very first time.
@Scheduled(fixedRate = 1000, initialDelay = 2000) public void scheduleTaskFixedRate() { logger.info("Fixed Rate Task : The task execution time is : " + Calendar.getInstance().getTime()); }
The task will run for the first time after the initialDelay value and the task will continue it’s execution according to the fixedDelay value.
Scheduling a task using Cron
In some cases, we need fine grained control to schedule tasks, in addition to delays and rates. Here is where, cron expressions come handy. The `cron` property gives flexibility to let us define seconds(0-59), minutes(0-59), hours(0-23), day of the month(1-31), month(0-11 or JAN-DEC), day of a week(1-7 or SUN-SAT) and even the year(1970-2099 or empty) that a task is scheduled to run. Is’nt it cool?
All the above mentioned fields(in the same order) except the year field are mandatory. You can even schedule a task to run at year 2099!
Apart from this, each field support special characters to provide detailed control over scheduling. For example, `*` represents all values. `?` represents no specific value and many more.
Hence, a cron expression is a string made up of 6-7 fields that are separated by a white space. The various combinations of the allowed values for the field provides powerful and flexible way to schedule tasks.
Lets go through a few examples.
@Scheduled(cron = "0 0 10 * * ? 2020")
The above cron expression fires at 10 AM, every day of the month, for each month, for the year 2020
@Scheduled(cron = "0 0 8 * * ?")
Fires at 8 AM everyday.
@Scheduled(cron = "0 10 10 * * ? 2021")
Fires at 10:10 AM everyday for the year 2021.
@Scheduled(cron = "0/30 * * * * ?")
Fire every 30 seconds.
@Scheduled("0 0 12 15 * ?")
Fires at every month on the 15th, at noon
Conclusion
In this article, we discussed to use the various functionalities for task scheduling with Spring Boot. The greatest advantage of scheduling tasks using Spring Boot is the ease with which it can be implemented, even by a novice programmer. If we need to require to schedule tasks that need to run quite frequently, it is ideal to configure the fixedRate or fixedDelay property. On the other hand, if we need to schedule tasks with higher execution time, it is ideal to configure the cron property. Apart from this, the cron property provides fine grained control of scheduling tasks, based on our requirements.
Schedulers are mandatory components of popular applications. This is because, most real-time applications are time-critical.