Spring provides an extensive support for task scheduling with different options to meet different requirements. The annotation used by spring is @Scheduled. In this article, we will see the possible ways we can use this annotation and the configuration which has to be done to support this annotation.
Also we will discuss about different configurations we can do around @Scheduled annotation to achieve various requirements.
Configuration to support scheduling
In order to use @Scheduled annotation, we need to first do some configuration in our spring application. For spring boot application or annotation based spring application, we use @EnableScheduling annotation in our configuration class something like below:
@Configuration @EnableScheduling public class AppConfiguration { } |
For XML based configuration following configuration is needed in applicationContext.xml
xmlns:task=”http://www.springframework.org/schema/task” http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd <task: annotation-driven> |
Rules on method using @Scheduled
The method we annotate with @Scheduled should follow below rules:
- The method should not contain any parameters.
- The return type of the method should be void.
- If the method needs some object, we need to inject that object in the method
and use it rather than passing as parameter.
@Scheduled with fixedRate and fixedDelay
fixedRate option is used to run the tasks at a fixed interval. Suppose a method needs to be run in every 5s interval, the fixedRate should be used with value 5s. It does not check whether previous execution of task is finished or not. So this option should be selected when the task executions are independent. The example is given below:
public class AppSchedule {
@Scheduled(fixedRate = 1000)
public void scheduleFixedRate() throws InterruptedException {
System.out.println(Thread.sleep(1000)) }
}
In this case the method scheduleFixedRate is scheduled to run at every 1s. But suppose a task is started and it couldn’t finish in 1s, then second execution won’t be invoked until the first one ended. Since there is no parallel processing here, so it will wait till the first one is done. To achieve parallel running of multiple task @Async annotation should also be added to the method
@EnableAsync public class AppSchedule { @Async @Scheduled(fixedRate = 1000) public void scheduleFixedRate() throws InterruptedException { System.out.println("Tasks start in every 1s" ) } }
fixedDelay is another option, which can be used with @Scheduled. This property is used when we want some minimum delay between the end of execution of one task and start of execution of another task. This will assure that only one task runs at a time. Below is the syntax of fixedDelay usage
public class AppSchedule { @Scheduled(fixedDelay = 1000) public void scheduleFixedRate() throws InterruptedException { System.out.println( "Tasks start after delay of 1s" ) } }
@Scheduled with Cron Expression
This option gives more flexibility to the task scheduling. Inspite of running the tasks on some fixed delays or fixed interval, the requirement can be to schedule the tasks on some particular time on every sunday. To meet such requirement we can use Cron option with @Scheduled. Lets see it with an example
public class AppSchedule { @Scheduled(cron = " 15 10 * * Sun") public void scheduleByCron() { System.out.println("Cron Job Running"+ new Date()) } }
This cron will job will run at 10:15 a.m. every sunday. If we want cron expression outside in some property file, that is possible using below syntax:
@Scheduled(cron = “${cron.expression}”)
cron.expression should be declared in application.yml or other property file as key and the expression should be given as value.
A little brief about what is the format of job:
+---------------- minute (0 - 59)
| +------------- hour (0 - 23)
| | +---------- day of month (1 - 31)
| | | +------- month (1 - 12)
| | | | +---- day of week (0 - 6) (Sunday=0 or 7)
| | | | |
* * * * *