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)