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)

👋 Kindness is contagious

Engage with a wealth of insights in this thoughtful article, valued within the supportive DEV Community. Coders of every background are welcome to join in and add to our collective wisdom.

A sincere "thank you" often brightens someone’s day. Share your gratitude in the comments below!

On DEV, the act of sharing knowledge eases our journey and fortifies our community ties. Found value in this? A quick thank you to the author can make a significant impact.

Okay