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>
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
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;
}
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();
}
}
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();
}
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)