What is a scheduler, how does Spring scheduled tasks function and how to use @Scheduled annotation in Spring?

A scheduler is used to execute a method in Java using some specific time-related dynamics, for example, you can configure it to execute your method:

  • on every two minutes
  • 5 mins after the previous execution
  • on every Monday at 13h
  • every day on 15:30h
  •  every first day in the month
  • ...

How to setup scheduler in Java - Spring?

. You can set up scheduled tasks in Spring by adding @Scheduled annotation on the method you would want to schedule. Also, you need to enable scheduling on the application level by adding @EnableScheduling annotation in the main class of your application.

@EnableScheduling
@SpringBootApplication
public class MyApp {
public static void main(String[] args) {
		SpringApplication.run(MyApp.class, args);
	}
...
}

It's important to mention that there are some basic limitations for those methods you would like to annotate with @Scheduled. If your code does not respect them, it will not compile and IDE will notify you about it. 

  • the method annotated with @Scheduled must return a void type
  • the method annotated with @Scheduled should not have any input parameters

How do I execute the same method in sequence with specific delays in between?

spring scheduler - fixed delay

To achieve this, just need to add an additional parameter to @Scheduled annotation - fixedDelay. This way, method execution starts after the previous execution is completed, and fixedDelay time passed. The number you define for fixedDelay represents time in milliseconds.

	@Scheduled(fixedDelay=6000)
	public void callExternalService() {
		...
	}

Adding delay to the first execution of the task method

If you want to add delay to the first execution of the method for some reason, you can use initialDelay parameter indicating the number of milliseconds to wait before the first execution of the method. And after that initial delay, fixed delay takes over, so methods are executed in sequence with provided fixed delay in between. So, this configuration would look like:

	@Scheduled(fixedDelay=6000, initialDelay=1000)
	public void callExternalService() {
		...
	}

How to schedule a task at the fixed rate?

@Scheduled annotation also has a parameter called fixedRate. It should be used in situations where method invocations are independent.

	@Scheduled(fixedRate=600)
	public void callExternalService() {
		...
	}

spring scheduler - fixed rate

What if my methods overlap while I use fixedRate?

If method execution should be able to overlap - execute in parallel in some moment of time, you should add @Async annotation to your service execution. Without @Async, method will always execute after the previous execution is completed, even if fixedRate expired. 

@EnableAsync
public class ExternalServiceCallExample{
    
    @Async
    @Scheduled(fixedRate = 600)
    public void callExternalService(){
        ...
    }
}

Configure scheduler using cron expression

Cron expression has six places and they represent:

second, minute, hour, day of month, month, day(s) of week.

scheduler - cron expression

When cron expression is met, the method is executed.

You can set timezone to be sure that the server zone will not influence your method execution. You can find a complete list of timezones on this link.

@Scheduled(cron="* * * * * *", zone="Asia/Tokyo")
public void callExternalService(){
        ...
    }

How to use parameters in the scheduler - or, how to parametrize scheduler?

Usually, you'll need to make all the mentioned parameters configurable outside the class because you don't want to compile and re-deploy the entire application every time you change something.

For this purpose, we're able to use Spring configuration parameters which are stored in property files. 

  • For fixed delay you'll use @Scheduled(fixedDelayString = "${fixedDelayInMilliseconds}")
  • For a fixed rate scheduled task you'll use Scheduled(fixedRateString = "${fixedRateInMilliseconds}")
  • For a scheduled task based on cron expression: @Scheduled(cron = "${cron.expression}")