By kswaughs | Thursday, September 19, 2024

Spring Boot ShedLock Example

Spring ShedLock is a distributed lock for scheduled tasks. It ensures that only one instance of a scheduled task runs at the same time in a distributed environment, such as a cluster of microservices. This is particularly useful for tasks that should not be executed concurrently, like data processing or cleanup jobs.

How ShedLock Works

Lock Provider: A lock provider is configured to manage the locks. This could be a database, Redis, etc.

Annotations: Tasks are annotated with @SchedulerLock to specify lock names and durations.

Execution: When a task is scheduled to run, ShedLock checks if a lock is available. If it is, the task runs and the lock is held for the specified duration.

Release: After the task completes or the lock duration expires, the lock is released, allowing other instances to acquire it.


Step 1. Add Dependencies


pom.xml
<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-spring</artifactId>
    <version>4.27.0</version>
</dependency>
<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-provider-jdbc-template</artifactId>
    <version>4.27.0</version>
</dependency>

Step 2. Create Configuration Class

Create a configuration class to set up ShedLock with a JDBC lock provider.

ShedLockConfig
package com.kswaughs.batch.config;

import net.javacrumbs.shedlock.core.LockProvider;
import net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateLockProvider;
import net.javacrumbs.shedlock.spring.annotation.EnableSchedulerLock;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;

@Configuration
@EnableSchedulerLock(defaultLockAtMostFor = "PT30S")
public class ShedLockConfig {

    @Bean
    public LockProvider lockProvider(JdbcTemplate jdbcTemplate) {
        return new JdbcTemplateLockProvider(
            JdbcTemplateLockProvider.Configuration.builder()
                .withJdbcTemplate(jdbcTemplate)
                .usingDbTime() // Works with PostgreSQL, MySQL, MariaDB, MS SQL, Oracle, DB2
                .build()
        );
    }
}

Step 3: Create Scheduled Task

Create a scheduled task that uses ShedLock to ensure only one instance of the task runs at a time.

ScheduledTasks
package com.kswaughs.batch.job;

import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ScheduledTasks {

    @Scheduled(cron = "0 0/5 * * * ?")
    @SchedulerLock(name = "TaskName", lockAtMostFor = "PT10M", lockAtLeastFor = "PT5M")
    public void performTask() {
        // Task implementation
        System.out.println("Scheduled task is running...");
    }
}

Step 4: Enable Scheduling

Ensure that scheduling is enabled in your Spring Boot application by adding @EnableScheduling to your main application class.

Main class
package com.kswaughs.batch;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

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

Step 5: Create Database Table - ShedLock

The ShedLock library does not create the table automatically. You need to create the table manually. Here is the SQL script to create the ShedLock table.

Database Table
CREATE TABLE shedlock(
    name VARCHAR(64) NOT NULL,
    lock_until TIMESTAMP(3) NOT NULL,
    locked_at TIMESTAMP(3) NOT NULL,
    locked_by VARCHAR(255) NOT NULL,
    PRIMARY KEY (name)
);

Key Features
Distributed LockingEnsures that only one instance of a task runs at a time across multiple nodes.
Multiple Lock ProvidersSupports various lock providers like JDBC, MongoDB, Redis, ZooKeeper, etc.
AnnotationsUses annotations like @SchedulerLock to easily lock scheduled tasks.
ConfigurationCan be configured using Spring's configuration classes and properties.
IntegrationSeamlessly integrates with Spring's @Scheduled tasks.

Benefits
Prevents Duplicate ExecutionEnsures that tasks are not executed concurrently in a distributed setup.
Easy to UseSimple annotations and configuration make it easy to integrate into existing Spring applications.
FlexibleSupports various backends for lock storage, making it adaptable to different environments.

Recommend this on