Quartz Scheduler Example

0

In this article we will see an example of Quartz Scheduler. The example demonstrates how to create a scheduler, job, trigger and then associate the job to the trigger. It then stats the scheduler, sleeps for few seconds and then shuts down the Scheduler.

Dependencies

Before we start with example, let’s add the necessary dependencies to our pom.xml.

  1. quartz – to use quartz scheduler
  2. slf4j-api – Simple Logging Facade for Java API for logging framework abstraction
  3. slf4j-log4j12 – log4j for the actual logging framework

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>1.0.0</modelVersion>
	<groupId>com.javarticles.junit</groupId>
	<artifactId>QuartzSchedulerExample</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<dependencies>
		<dependency>
			<groupId>org.quartz-scheduler</groupId>
			<artifactId>quartz</artifactId>
			<version>2.2.1</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>1.7.12</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.7.12</version>
		</dependency>		
	</dependencies>

</project>

Create a Job

A job is a class that implements the Job interface. Below is a simple job that implements the Job interface and prints ‘Hello Quartz!’ with the current date and time.

SayHelloJob:

package com.javarticles.quartz;

import java.util.Date;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class SayHelloJob implements Job {

    public SayHelloJob() {
    }

    public void execute(JobExecutionContext context) throws JobExecutionException {
        // Say Hello to the World and display the date/time
        System.out.println("Hello Quartz! - " + new Date());
    }

}

Get Scheduler

In order to schedule the job, we first need the scheuler. This is done by creating a StdSchedulerFactory and then using it to create a scheduler.

SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();

One can customize the behavior of quartz using a properties file. As soon as we instantiate StdSchedulerFactory, it initializes itself with the contents of quartz properties. By default quartz scheduler looks for “quartz.properties” from the current working directory. If the quarts properties file is somewhere else then you can provide the file path in the system property ‘org.quartz.properties’. If the file is not found then it looks for ‘quartz.properties’ in the classpath. You can override the properties in file using the System properties.

The scheduler instantiated is cached so multiple calls to schedulerFactory.getScheduler() will return the same scheduler. If the scheduler is down then it will replace the scheduler in cache with a new one.

When a scheduler is first created, the scheduler thread is started but it remains in stand-by mode, will not fire trigger until the scheduler is started.
We start the scheduler using start() and shutdown using shutdown(). The scheduler can also be put into stand-by mode by calling the standby() method.

Create JobDetail

We already have seen the class SayHelloJob that does the actual work but the job itself may need assistance of various attributes that you want the job to have access to. This additional information about the job is passed in via the JobDetail class.

JobDetail jobDetail = JobBuilder.newJob(SayHelloJob.class)
                    .withIdentity("myJob", "myGroup").build();

Create Trigger

Trigger objects define the schedule when a job needs to be executed. In our example, we use SimpleTrigger to execute the job starting at a specific moment in time followed by repeats at a specific interval.

SimpleTrigger trigger = TriggerBuilder
                    .newTrigger()
                    .withIdentity("myTrigger", "myGroup")
                    .startAt(startTime)
                    .withSchedule(
                            SimpleScheduleBuilder
                                    .simpleSchedule()
                                    .withIntervalInSeconds(5)
                                    .repeatForever()
                                    .withMisfireHandlingInstructionIgnoreMisfires())
                    .build();

Schedule the job

We now will associate the job to the trigger in the scheduler and then start the scheduler.

scheduler.scheduleJob(jobDetail, trigger);
scheduler.start();

Job Execution Context

When a job’s trigger fires, the Job.execute() method is invoked by one of the Scheduler’s
worker threads. The JobExecutionContext object that is passed to this method provides the job instance with information about its run-time environment, including a handle to the scheduler that executed it, a handle to the trigger that triggered the execution, the job’s JobDetail object, and a few other items.

public interface JobExecutionContext {

    Scheduler getScheduler();
    Trigger getTrigger();
    Calendar getCalendar();
    JobDataMap getMergedJobDataMap();
    JobDetail getJobDetail();
....
}

Run Quartz Scheduler Example

Here is the complete example. After the start of scheduler, we make the main thread to sleep for 9 seconds so that the scheduler thread gets a chance to run the job.

QuartzSchedulerExample:

package com.javarticles.quartz;

import java.util.Date;

import org.quartz.DateBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;

public class QuartzSchedulerExample {
    public static void main(String[] args) throws SchedulerException {
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        Scheduler scheduler = schedulerFactory.getScheduler();
        try {            
            JobDetail jobDetail = JobBuilder.newJob(SayHelloJob.class)
                    .withIdentity("myJob", "myGroup").build();
            Date startTime = DateBuilder.evenMinuteDateBefore(null);
            SimpleTrigger trigger = TriggerBuilder
                    .newTrigger()
                    .withIdentity("myTrigger", "myGroup")
                    .startAt(startTime)
                    .withSchedule(
                            SimpleScheduleBuilder
                                    .simpleSchedule()
                                    .withIntervalInSeconds(5)
                                    .repeatForever()
                                    .withMisfireHandlingInstructionIgnoreMisfires())
                    .build();
            scheduler.scheduleJob(jobDetail, trigger);
            scheduler.start();
            try {
                Thread.sleep(9000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        } finally {
            try {
                scheduler.shutdown();
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        }

    }
}

Output:

18:37| INFO | StdSchedulerFactory.java 1184 | Using default implementation for ThreadExecutor
18:37| INFO | SimpleThreadPool.java 268 | Job execution threads will use class loader of thread: main
18:37| INFO | SchedulerSignalerImpl.java 61 | Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
18:37| INFO | QuartzScheduler.java 240 | Quartz Scheduler v.2.2.1 created.
18:37| INFO | RAMJobStore.java 155 | RAMJobStore initialized.
18:37| INFO | QuartzScheduler.java 305 | Scheduler meta-data: Quartz Scheduler (v2.2.1) 'DefaultQuartzScheduler' with instanceId 'NON_CLUSTERED'
  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
  Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.

18:37| INFO | StdSchedulerFactory.java 1339 | Quartz scheduler 'DefaultQuartzScheduler' initialized from default resource file in Quartz package: 'quartz.properties'
18:37| INFO | StdSchedulerFactory.java 1343 | Quartz scheduler version: 2.2.1
18:37| INFO | QuartzScheduler.java 575 | Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.
Hello Quartz! - Sat Mar 19 18:37:04 IST 2016
Hello Quartz! - Sat Mar 19 18:37:05 IST 2016
Hello Quartz! - Sat Mar 19 18:37:10 IST 2016
18:37| INFO | QuartzScheduler.java 694 | Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutting down.
18:37| INFO | QuartzScheduler.java 613 | Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED paused.
18:37| INFO | QuartzScheduler.java 771 | Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutdown complete.

Quartz Scheduler Model

Here is the quartz scheduler model diagram. You can read more about it here.

Quartz Scheduler Model

Quartz Scheduler Model

Download the source code

This was an example about Quartz Scheduler.

You can download the source code here: quartzSchedulerExample.zip

About Author

Ram's expertise lies in test driven development and re-factoring. He is passionate about open source technologies and loves blogging on various java and open-source technologies like spring. You can reach him at rsatish.m@gmail.com

Comments are closed.