DEV Community

Ahmad Naqibul Arefin
Ahmad Naqibul Arefin

Posted on

Quartz Scheduler with Spring Boot and PostgreSQL in a Clustered Environment

Setting up Quartz Scheduler in a distributed, clustered Spring Boot environment allows multiple instances of your application to coordinate scheduled tasks without conflicts or duplications. Here's a comprehensive, step-by-step guide for a production-ready setup:

Step 1: Adding Dependencies (pom.xml)

Add Quartz and PostgreSQL dependencies to your project:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <scope>runtime</scope>
</dependency>
Enter fullscreen mode Exit fullscreen mode

2. Database Setup

Create a PostgreSQL database (e.g., quartz_db) and initialize Quartz tables using the provided Quartz schema:

  • Locate the schema script: docs/dbTables/postgresql.sql in the Quartz distribution.
  • Execute this script against your PostgreSQL database to generate Quartz tables (e.g., QRTZ_JOB_DETAILS, QRTZ_TRIGGERS).

3. Quartz Configuration (application.yml)

Configure Quartz properties for clustering and PostgreSQL persistence:

spring:
  quartz:
    job-store-type: jdbc
    jdbc:
      initialize-schema: never
    properties:
      org.quartz.jobStore.class: org.springframework.scheduling.quartz.LocalDataSourceJobStore
      org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
      org.quartz.jobStore.isClustered: true
      org.quartz.jobStore.clusterCheckinInterval: 10000
      org.quartz.scheduler.instanceId: AUTO
      org.quartz.scheduler.instanceName: ClusteredQuartzScheduler
      org.quartz.threadPool.threadCount: 5
Enter fullscreen mode Exit fullscreen mode

4. Spring Quartz Scheduler Configuration

Define Quartz's SchedulerFactoryBean and a custom JobFactory to enable Spring-managed dependency injection:

@Configuration
public class QuartzConfig {

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource, PlatformTransactionManager transactionManager, JobFactory jobFactory, Trigger jobTrigger) {
        SchedulerFactoryBean scheduler = new SchedulerFactoryBean();
        scheduler.setDataSource(dataSource);
        scheduler.setTransactionManager(transactionManager);
        scheduler.setJobFactory(jobFactory);
        scheduler.setTriggers(sampleJobTrigger);
        return scheduler;
    }
Enter fullscreen mode Exit fullscreen mode

5. Defining a Job

Create a Quartz job implementing the Job interface:

@Component
public class MyQuartzJob implements Job {

    @Autowired
    private MyService myService;

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        myService.executeTask();
    }
}
Enter fullscreen mode Exit fullscreen mode

6. Scheduling the Job

Schedule the job to trigger every 15 minutes:

@Bean
public JobDetail sampleJobDetail() {
    return JobBuilder.newJob(SampleJob.class)
        .withIdentity("sampleJob")
        .storeDurably()
        .build();
}

@Bean
public Trigger sampleJobTrigger(JobDetail sampleJobDetail) {
    return TriggerBuilder.newTrigger()
        .forJob(sampleJobDetail)
        .withSchedule(CronScheduleBuilder.cronSchedule("0 0/15 * * * ?"))
        .build();
}
Enter fullscreen mode Exit fullscreen mode

7. Ensuring Clustered Execution

Ensure all your application instances share the same PostgreSQL database configuration and Quartz properties (isClustered=true). Quartz internally coordinates using the database to avoid concurrent execution of the same job by multiple nodes.

8. Testing and Deployment

  • Run multiple application instances pointing to the same database.
  • Monitor logs to verify that jobs run exclusively on a single node per trigger interval.
  • Check Quartz's cluster tables (e.g., QRTZ_SCHEDULER_STATE) to ensure nodes register correctly.

This guide ensures robust, coordinated job scheduling with Quartz and Spring Boot in a distributed environment using PostgreSQL.

Top comments (0)