Explain Codes LogoExplain Codes Logo

How to Parameterize @Scheduled(fixedDelay) with the Spring 3.0 Expression Language

java
spring-boot
scheduled-tasks
parameterization
Anton ShumikhinbyAnton Shumikhin·Dec 3, 2024
TLDR

In Spring v3.2.2+, you can dynamically control the fixedDelay of the @Scheduled annotation by using a property value from a configuration source, such as application.properties. Example:

@Scheduled(fixedDelayString = "${task.schedule.delay}") public void scheduledTask() { // Your task here ➡️ feed the cat 🐱 }

Just define it in application.properties like so:

task.schedule.delay=3000 // Delay in milliseconds, change it as you would change your socks

By doing so, you can flexibly alter the fixedDelay without having to recompile your code.

Configuring Task Scheduling Made Easy

Starting from Spring v3.2.2, fixedDelay, fixedRate, and initialDelay support String parameters, such as fixedDelayString. They can read property values directly from application.properties or even from environment variables. This flexibility allows for effective management of the frequency and timing of your scheduled tasks.

Parsing String to Long for Fixed Delay

When dealing with frequencies of less than 1 second, a defined bean that parses the configuration value can come in handy:

// This bean is the real MVP ⭐ @Bean public Long fixedDelay() { return Long.valueOf(environment.getProperty("task.schedule.delay")); }

You can then inject this bean using @Value like so:

@Scheduled(fixedDelayString = "#{@fixedDelay}") public void scheduledTaskWithBean() { // Task doing bean things ☕️ }

Also, the T(Long).valueOf() expression provides a way to convert Strings to Long for fixedDelay, quite handy for XML configurations.

The Precision of Cron Expressions

For more precise task scheduling requirements, you can utilize cron expressions. The cron parameter of the @Scheduled annotation can exploit cron expression directly from the config file:

@Scheduled(cron = "${cronSchedule}") public void scheduledTaskWithCron() { // Task is as precise as a Swiss watch }

In application.properties, you define:

cronSchedule=*/5 * * * * * // Every 5 seconds

Scheduled Tasks via XML Configuration

If you are more comfortable with XML configuration, you can parameterize fixedDelay using the SpEL expression within the configuration XML file:

<task:scheduled ref="taskRunner" method="performTask" fixed-delay="#{T(Long).valueOf('${task.schedule.delay}')}"/>

This capability provides a great alternative for those who prefer more traditional XML-based configurations.

Leverage Spring Boot for Simple Scheduling

Spring Boot 2.x offers an even simpler way to handle dynamic scheduling using the fixedRateString parameter. Coupling it with the profile-specific properties, you can tailor your task schedules to your different environments:

application-dev.properties:

task.fixedRate=10000  // 10 seconds for development

application-prod.properties:

task.fixedRate=15000  // 15 seconds for production

This allows your application to be more adaptive to different deployment environments or scenarios.

Use Spring's Environment Abstraction for Property Management

The Environment abstraction in Spring enables dynamic property access, meaning you can always adapt your @Scheduled tasks according to different environments and scenarios.