Master Quartz Scheduler in Spring Boot: From Basics to Advanced Persistence
This article provides a comprehensive guide to using Quartz in Java Spring Boot, covering core concepts, basic and advanced usage—including job creation, triggers, Cron expressions, bean injection, multiple triggers, and persistence with JDBC—complete with code samples and configuration steps.
1. Introduction to Quartz
If you need a non‑distributed scheduled task with dynamic management such as start, pause, resume, stop, or modify trigger times, Quartz is an excellent choice.
Quartz is a powerful Java scheduling framework developed by OpenSymphony, consisting of three main components: Job , Trigger , and Scheduler .
Job : the actual work to be executed.
Trigger : defines when and how often the job runs.
Scheduler : assembles jobs and triggers and executes them.
Analogy: Job is a product, Trigger is a production line, Scheduler is the workshop manager.
2. Basic Usage
2.1 Interval‑Based Task
Add the Spring Boot starter for Quartz:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>Create a Job class implementing org.quartz.Job:
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class SimpleJob implements Job {
@Override
public void execute(JobExecutionContext ctx) {
System.out.println(Thread.currentThread().getName() + "--"
+ DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
.format(LocalDateTime.now()));
}
}Configure Scheduler, JobDetail and a SimpleTrigger that runs every 2 seconds for 30 seconds:
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler scheduler = sf.getScheduler();
JobDetail jobDetail = JobBuilder.newJob(SimpleJob.class)
.withIdentity("job1", "group1")
.build();
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger-1", "trigger-group")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(2)
.repeatForever())
.build();
scheduler.scheduleJob(jobDetail, trigger);
scheduler.start();
TimeUnit.SECONDS.sleep(30);
scheduler.shutdown();The console shows the thread‑pool size (default 10) and confirms the scheduler uses an internal thread pool.
2.2 Cron‑Expression Task
Define a CronTrigger with a cron expression, e.g. “* 30 10 ? * 1/5 *”:
CronTrigger cronTrigger = TriggerBuilder.newTrigger()
.withIdentity("trigger-1", "trigger-group")
.startNow()
.withSchedule(CronScheduleBuilder.cronSchedule("* 30 10 ? * 1/5 *"))
.build();
scheduler.scheduleJob(jobDetail, cronTrigger);
scheduler.start();
TimeUnit.SECONDS.sleep(30);
scheduler.shutdown();3. Deep Dive into Quartz
The main classes and their relationships are illustrated below:
JobDetail : built by JobBuilder, uniquely identified by name and group.
Trigger : built by TriggerBuilder, defines execution schedule; one‑to‑many relationship with JobDetail.
Scheduler : core component that manages jobs and triggers.
JobDataMap : a map attached to JobDetail for passing parameters.
JobStore : persists job and trigger metadata; two implementations are RAMJobStore (in‑memory) and JDBCJobStore (database).
3.1 Job
A Job implements a single execute() method. Use JobBuilder to create a JobDetail and register it with the Scheduler.
3.2 Trigger Types
SimpleTrigger : interval‑based execution with repeat count or end time.
CronTrigger : cron‑expression based execution.
CalendarIntervalTrigger : calendar‑aware intervals (handles month length, leap years).
DailyTimeIntervalTrigger : executes within a daily time window.
Trigger states include NONE, NORMAL, PAUSED, COMPLETE, ERROR, and BLOCKED.
3.3 Scheduler API
Control scheduler lifecycle: start(), shutdown().
Job operations: addJob(), pauseJob(), resumeJob(), getJobDetail(), etc.
Trigger operations: pauseTrigger(), resumeTrigger(), etc.
4. Advanced Usage
4.1 Multiple Triggers for One Job
Mark a JobDetail as durable, add it to the scheduler without a trigger, then attach several triggers using forJob(jobDetail) and scheduleJob(trigger).
JobDetail jobDetail = JobBuilder.newJob(SimpleJob.class)
.withIdentity("job1", "job-group")
.storeDurably()
.build();
Trigger trigger1 = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "trigger-group")
.startNow()
.forJob(jobDetail)
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(2)
.repeatForever())
.build();
Trigger trigger2 = TriggerBuilder.newTrigger()
.withIdentity("trigger2", "trigger-group")
.startNow()
.forJob(jobDetail)
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(3)
.repeatForever())
.build();
scheduler.addJob(jobDetail, false);
scheduler.scheduleJob(trigger1);
scheduler.scheduleJob(trigger2);
scheduler.start();
TimeUnit.SECONDS.sleep(20);
scheduler.shutdown();4.2 Injecting Beans into a Job
Two approaches:
Use JobDataMap to pass a mapper or service instance (requires the object to be serializable).
Define a static utility that implements ApplicationContextAware to fetch beans from the Spring context at runtime.
Example of the utility class:
@Component
public class SpringContextJobUtil implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext ctx) throws BeansException {
context = ctx;
}
public static Object getBean(String name) {
return context.getBean(name);
}
}Job can retrieve the mapper with SpringContextJobUtil.getBean("personMapper").
4.3 Quartz Persistence
To persist jobs, add a connection‑pool dependency (e.g., c3p0) and configure a SchedulerFactoryBean that loads quartz.properties. The properties file defines the thread pool, job store class ( org.quartz.impl.jdbcjobstore.JobStoreTX), data source, and table prefix.
SQL scripts to create the Quartz tables (MySQL example) are provided in the official Quartz distribution. After configuring the data source and job store, Quartz stores job and trigger metadata in the database, enabling recovery after application restarts.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
