Problem
Owing to my web application will deploy to a cluster, so I need to find a solution to prevent concurrent execution of scheduled Spring tasks.
Here has a short example to demo how to use shedlock.
How-To
Add dependencies in pom.xml
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-spring</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-provider-jdbc-template</artifactId>
<version>1.0.0</version>
</dependency>
Create table for shedlock
CREATE TABLE MY_BATCH_LOCK(
name VARCHAR(64),
lock_until TIMESTAMP(3) NULL,
locked_at TIMESTAMP(3) NULL,
locked_by VARCHAR(255),
PRIMARY KEY (name)
)
Add configuration in your spring boot application
package demo.config;
import java.time.Duration;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import net.javacrumbs.shedlock.core.LockProvider;
import net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateLockProvider;
import net.javacrumbs.shedlock.spring.ScheduledLockConfiguration;
import net.javacrumbs.shedlock.spring.ScheduledLockConfigurationBuilder;
@Configuration
public class ShedlockConfig {
@Bean
public LockProvider lockProvider(DataSource dataSource) {
return new JdbcTemplateLockProvider(dataSource, "MY_BATCH_LOCK");
}
@Bean
public ScheduledLockConfiguration scheduledLockConfiguration(LockProvider lockProvider) {
return ScheduledLockConfigurationBuilder
.withLockProvider(lockProvider)
.withPoolSize(10)
.withDefaultLockAtMostFor(Duration.ofMinutes(10))
.build();
}
}
Usage:
private static final int TEN_MIN = 10 * 60 * 1000;
@Scheduled(cron = "0 0 1 * * ?")
@SchedulerLock(name = "mySchedulerTask", lockAtMostFor = TEN_MIN, lockAtLeastFor = TEN_MIN)
public void execute() {
}