Working with Quartz Scheduler using Spring Boot

Shubham Wankhede
5 min readMar 18, 2023

--

if you are working in Software Development for long period of time it’s most likely that you might have heard about quartz scheduler, yes as the name says it is used to schedule and execute a task/job at a specific date and time.

well if you have heard about quartz scheduler it’s impossible that you have not heard about spring boot scheduler, so what’s the difference between them and when to use which scheduler

before we get into any heated discussion about which scheduler to use either Spring Boot Scheduler or Quartz Scheduler let me highlight few things

as we know spring boot provides abstraction on most of the open source libraries available to make simplest use of them, same thing is true with Spring Boot Scheduler as well

Yes, Spring Boot Scheduler library uses Quartz Scheduler library internally for scheduling a task, if you look at the TaskScheduler or @Scheduled annotation for which spring creates a Scheduler object and this scheduler object is implemented using SchedulerFactoryBean which uses Quartz Library

so the main point here is instead of comparing which library is better, it’s best that we look into which one to use when i.e. either Spring Boot Scheduler or to use Quartz Library directly

Simply putting in words you can use Spring Boot Scheduler most of time for interval job execution

we can use Quartz Scheduler when

  1. when the in scheduling you have to execute task at a irregular interval
  2. when you have to decide the specific date and time to start the task
  3. you want misfire handling, job persistance etc.

on how to work with spring boot scheduler you can follow this blog : https://wankhedeshubham.medium.com/want-to-execute-task-on-scheduled-period-spring-boot-scheduler-f9c1e71ba165

now let’s understand how to directly work with Quartz Scheduler library using Spring Boot, before we get started let’s look at different components which we need or we can use while working with Quartz Scheduler

we are going to use QuartzScheduler to schedule a job/task.

the steps we need to follow and components we need to get started with most schedule a job is

  1. writing job store configuration
  2. Creating Job Bean
  3. Creating Trigger and Job Details
  4. Scheduler Job using Quartz Scheduler

let’s understand each steps

Step 1: Job Store Configuration

configure below configurations in application.properties

#store type either in-memory or jdbc to store in DB
spring.quartz.job-store-type=jdbc
p
#to create tables used to store job and other scheduling activities
spring.quartz.jdbc.initialize-schema=always

#datasource to store jobs in DB if store type is jdbc
spring.datasource.username=
spring.datasource.password=
spring.datasource.url=jdbc:h2:file:D:/H2_DB/quartz.db
spring.datasource.driver=org.h2.Driver
spring.h2.console.enabled=true

spring.jpa.hibernate.ddl-auto=update

org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate

# if you want to provide multiple threads to run jobs
spring.quartz.properties.org.quartz.threadPool.threadCount=5

let’s understand few of these configuration

spring.quartz.job-store-type=jdbc property is used to define the job store we want to use in this case the value jdbcrepresents that we want to store job, triggers etc in Datasource configured

we can also use value as memory which is used to store job in in-memory

we need Quartz tables to store jobs in database we can use initilize property spring.quartz.jdbc.initialize-schema=always to automatically create the tables required is used to automatic

if you want to create tables manually you can use the official SQL script provided by quartz (https://github.com/callicoder/spring-boot-quartz-scheduler-email-scheduling/blob/master/src/main/resources/quartz_tables.sql)

we can also configure the number of concurrent threads we can use using spring.quartz.properties.properties.properties.org.quartz.threadpool.threadCount=5

aside from this we have to configure DB properties where we are going to store the jobs it can H2 DB or others.

Step 2: Creating Job Bean

to create a job we have to create a .java file extends it with QuartzJobBean

@Component
public class RecordCreationJob extends QuartzJobBean {

@Autowired
private RecordRepository recordRepository;

@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
String dataPassed = context.getMergedJobDataMap().get("dataPassed").toString();
System.out.println("Data Passed From Job Details : " + dataPassed);

System.out.println("Print Records : ");
recordRepository.findAll().stream().forEach(System.out::println);
}
}

in executeInternal method we have to write the logic we want to execute at scheduled period

Step 3: Creating Trigger and Job Details

we are going to create a service class from where we are going to schedule a job and since to schedule a job we need Trigger and Job Details we are going to create them in service class only

JobDetails

public JobDetail buildJobDetails(){
//create map to store key-value (can be received from request) which can be passed to job
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put("dataPassed", "Data can be passed to job it can be request Data or other" );

return JobBuilder.newJob(RecordCreationJob.class)
.withIdentity(UUID.randomUUID().toString(),"record-jobs") // unique job key
.withDescription("Record Job Description")
.usingJobData(jobDataMap) // values to pass to job
.storeDurably(true) //false - delete job once job executed
.build();
}

JobDataMap contains some properties we want to pass to our job which we are going to execute on schedule, these properties can be received from request when we are scheduling an event.

Identity of Job need to unique so as to uniquely identify them in table

if we want to delete the job from Job Store once we are done executing it then we can keep storeDurably(false)

Trigger

public Trigger buildTrigger(JobDetail jobDetail){
ZonedDateTime zonedDateTime = ZonedDateTime.of(LocalDate.parse("2023-04-01"),
LocalTime.of(8,30), ZoneId.of("Asia/Kolkata"));

return TriggerBuilder.newTrigger()
.forJob(jobDetail)
.withIdentity(jobDetail.getKey().getName(),"records-tigger")
.withIdentity("Records Trigger Description")
.startAt(Date.from(zonedDateTime.toInstant()))
/*
// Some Scheduler Example
.withSchedule(impleScheduleBuilder.simpleSchedule().withIntervalInHours(1))

--> cron scheduler
.withSchedule(CronScheduleBuilder.cronSchedule("0 0 16 * * ?")
.withMisfireHandlingInstructionFireAndProceed())

*/
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5).repeatForever())
.build();



}

since the job can be executed in any time zone we are providing the zoned time to start time of job

Note: one job can have multiple trigger but one trigger can only have one job

we can schedule job using cron expression or in interval for Quartz library has provided different schedules

Step 4: Scheduler Job using Quartz Scheduler

last but not least is to schedule a job using JobDetails and Trigger



@Service
public class RecordService {

@Autowired
private Scheduler quartzScheduler;

public void scheduleRecordPrinter(){
try {
JobDetail jobDetail = .buildJobDetails();
Trigger trigger = buildTrigger(jobDetail);
quartzScheduler.scheduleJob(jobDetail,trigger);
} catch (SchedulerException e) {
throw new RuntimeException(e);
}
}


//Implementation of trigger and jobdetails are mentioned above
public Trigger buildTrigger(JobDetail jobDetail){ .... }
public JobDetail buildJobDetails(){ ... }

}

here you can see I’ve autowired the Scheduler spring bean which is QuartzScheduler implementation

we need to use scheduleJob method and then pass trigger and job detail to schedule a job

Calling Scheduler

now we can call this scheduler from main method or if you are scheduling an event and are passing details start date and job specific data we call it from rest endpoint method

we are going to test it from main method

SpringBootApplication
public class QuartzSchedulerApplication {

public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(QuartzSchedulerApplication.class, args);

RecordService recordService = context.getBean(RecordService.class);
recordService.scheduleRecordPrinter();
}
}

with this we are done with simple quartz scheduler application.

--

--