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)