Quartz

Quartz Scheduler Cron Expression Example

Quartz scheduler offers two kind of triggers, simple trigger and cron trigger. If the schedule is based on specified intervals then a simple trigger will do but if your job needs to be fired based on calendar-like notions then you need to use cron triggers. For example, every Wednesday at 12:00:00 pm. From the name you can guess, cron expressions are based on the unix tool cron. We will use the cron expressions to build cron trigger. In this article, we will see examples of Quartz scheduler’s cron expressions.

Before we start with the example, let’s look into the basics.

1. What is Quartz?

Quartz is a Java open source job-scheduling system capable of scheduling and executing jobs. In this example, we use the latest stable Quartz available which is version 2.2.1.

Ok, we know what is Quartz but what is job here? A job is a Java class containing the task to be executed but how do we schedule it?. We schedule the job using the trigger which defines when to execute the job. We now know the basic components that Quartz is made up of. Once we start with an example you will know their roles. Let’s start with the Quartz setup.

2. Quartz Setup

In this example, we will use Maven as the build tool so all you need to do is add the below dependency to pom.xml which looks like below.

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>4.0.0</modelVersion>
	<groupId>com.javacodegeeks.camel</groupId>
	<artifactId>camelHelloWorld</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<dependencies>
		<dependency>
			<groupId>org.quartz-scheduler</groupId>
			<artifactId>quartz</artifactId>
			<version>2.2.1</version>
		</dependency>
	</dependencies>
</project>

Let’s begin our article with an example.

3. Example of Cron Expression

In our example, we first create a schedule, a job that needs to be executed, a trigger that defines when to execute and then finally scheduling the job. Our focus is on the cron trigger. We want to fire a job every day starting at 10:20:20. The time at which the first job fires is just a minute from now. Assuming the current time is 23:23:45, the cron expression would be “0 24 23 * * ? *”. The * defines

Here is the cron expression class which we will later use to build the trigger and schedule the job. CronTrigger instances are built using TriggerBuilder (for the trigger’s main properties)
and CronScheduleBuilder.

CronExpressionsExample:

package com.javacodegeeks.quartz;

import org.quartz.CronScheduleBuilder;
import org.quartz.DateBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;

public class CronExpressionsExample {
	private static final String GROUP_NAME = "CroneExamples";	
	
	// Fire at current time + 1 min every day
	public static Trigger fireAfterAMinEveryDayStartingAt(int startHr, int startMin, int startSec, int nowMin, int nowHr) {
		Trigger trigger = TriggerBuilder.newTrigger()
				.withIdentity("fireAfterAMinStartingAt", GROUP_NAME)
				.startAt(DateBuilder.todayAt(startHr, startMin, startSec))
				.withSchedule(CronScheduleBuilder.cronSchedule("0 " + (nowMin + 1) + " " + nowHr + " * * ? *"))		
				.build();
		return trigger;
	}
}

In order to understand the cron expression “0 24 23 * * ? *” and the individual components we need to understand its sub-expressions.

4. Cron Expression Components

Cron-Expressions are strings that are actually made up of seven sub-expressions. Each sub-expression describes the individual details of the schedule. These sub-expression are separated with white-space.

The sub-expressions represent the following components:

  1. Seconds
  2. Minutes
  3. Hours
  4. Day-of-Month
  5. Month
  6. Day-of-Week
  7. Year (optional field)

In our example, we have used wild cards * and ?. Wild-cards * means “every” possible value of this field whereas wild card? is used to specify “no specific value”. It is allowed for the day-of-month and day-of-week fields. Cron expression “0 24 23 * * ? *” means the job will fire at time 23:24:00 every day.

QuartzSchedulerCronTriggerExample:

package com.javacodegeeks.quartz;

import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.CountDownLatch;

import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;


public class QuartzSchedulerCronTriggerExample implements ILatch {
	private CountDownLatch latch = new CountDownLatch(1);
	public static void main(String[] args) throws Exception {	
		QuartzSchedulerCronTriggerExample quartzSchedulerExample = new QuartzSchedulerCronTriggerExample();
		quartzSchedulerExample.fireJob();
	}
	
	public void fireJob() throws SchedulerException, InterruptedException {
		SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
		Scheduler scheduler = schedFact.getScheduler();
		scheduler.start();
		
		// define the job and tie it to our HelloJob class
		JobBuilder jobBuilder = JobBuilder.newJob(MyJob.class);
		JobDataMap data = new JobDataMap();
		data.put("latch", this);
		
		JobDetail jobDetail = jobBuilder.usingJobData("example", "com.javacodegeeks.quartz.QuartzSchedulerListenerExample")	
				.usingJobData(data)
				.withIdentity("myJob", "group1")
				.build();
		
		Calendar rightNow = Calendar.getInstance();
		int hour = rightNow.get(Calendar.HOUR_OF_DAY);
		int min = rightNow.get(Calendar.MINUTE);
		
		System.out.println("Current time: " + new Date());				
		
		// Tell quartz to schedule the job using our trigger
		// Fire at current time + 1 min every day
		scheduler.scheduleJob(jobDetail, CronExpressionsExample.fireAfterAMinEveryDayStartingAt(10, 20, 20, hour, min));
		latch.await();
		System.out.println("All triggers executed. Shutdown scheduler");
		scheduler.shutdown();
	}
	
	public void countDown() {
		latch.countDown();
	}
}

MyJob:

package com.javacodegeeks.quartz;

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

public class MyJob implements Job {
	private static int count;

	public void execute(JobExecutionContext jobContext) throws JobExecutionException {
		System.out.println("--------------------------------------------------------------------");
		System.out.println("MyJob start: " + jobContext.getFireTime());
		JobDetail jobDetail = jobContext.getJobDetail();
		System.out.println("Example name is: " + jobDetail.getJobDataMap().getString("example"));		
		System.out.println("MyJob end: " + jobContext.getJobRunTime() + ", key: " + jobDetail.getKey());
		System.out.println("MyJob next scheduled time: " + jobContext.getNextFireTime());
		System.out.println("--------------------------------------------------------------------");
		
		ILatch latch = (ILatch) jobDetail.getJobDataMap().get("latch");
		latch.countDown();
		count++;
		System.out.println("Job count " + count);		
	}

}

ILatch:

package com.javacodegeeks.quartz;

public interface ILatch {
	void countDown();
}

Output:

Current time: Tue Sep 15 23:23:45 IST 2015
Fire every day starting at (10:20:20), start the job in a min from now->(0 24 23 * * ? *)
--------------------------------------------------------------------
MyJob start: Tue Sep 15 23:24:00 IST 2015
Example name is: com.javacodegeeks.quartz.QuartzSchedulerListenerExample
MyJob end: -1, key: group1.myJob
MyJob next scheduled time: Wed Sep 16 23:24:00 IST 2015
--------------------------------------------------------------------
Job count 1
All triggers executed. Shutdown scheduler

5. Allowed Values in Cron Expressions

The sub-expressions represent the following components. Let’s go through each component and take a note of the valid values.

  1. Seconds
  2. Minutes
  3. Hours
  4. Day-of-Month
  5. Month
  6. Day-of-Week
  7. Year (optional field)

6. Seconds and Minutes

Valid values for seconds and minutes are 0 to 59. Of course you can also use wild-cards which we will review in a separate section.

7. Hours

Valid values are 0 to 23 for hours.

8. Day of Month

In numerical form, 1-31, but you need to be careful about how many days are in a given month.

9. Months

Months can be specified both in numerical as well as string. For example, in string, using JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV and DEC. Months can also be specified using a numerical value between 0 and 11.

10. Day of Week

The day of the week can contain ranges strings SUN, MON, TUE, WED, THU, FRI and SAT. It can also use the numerical value instead, for example, any value between 1 and 7, starting Sunday (1).

We can also specify ranges like “MON-FRI”, “MON,WED,FRI”, or even “MON-WED,SAT”.

11. Special Characters in Cron Expressions

  1. * used to say “every” possible value of this field.
  2. / can be used to specify increments to values. For example, if you put ‘0/10’ in the Minutes field, it means ‘every 10th minute of the hour, starting at minute zero’.
  3. ? is allowed for the day-of-month and day-of-week fields. It is used to specify “no specific value”. This is useful when you need to specify something in one of
    the two fields, but not the other.
  4. L character is allowed only for the day-of-month and day-of-week fields. It means “last”, for example, L in the day-of-month field means “the last day of the month”
  5. W is used to specify the weekday (Monday-Friday) nearest the given day. For an example, if you were to specify “15W” as the value for the day-of-month field, it would mean “the nearest weekday to the 15th of the month”.
  6. The # is used to specify “the nth” XXX weekday of the month. For example, the value of “6#3” or “FRI#3” in the day-of-week field means “the third Friday of the month”.
  7. - is used to specify ranges. For example, “10-12” in the hour field means “the hours 10, 11 and 12.”
  8. , use comma separated values to specify additional values. For example, “MON,WED,FRI”

12. Examples of Cron Expressions

Below are some more cron expressions for various scenarios.

  1. 0 0 15 10 * * 20015 – Fire at 10:15am every day during the year 2015
  2. 0 0 10-15 * * ? – Fire between 10AM and 3PM every day
  3. 0 0 10-15 * * SAT-SUN – Fire between 10AM and 3PM on weekends SAT-SUN
  4. 0 0 10 14,18,21 * ? – Fire only on certain days of month (14,18 and 21)
  5. 0 46/2 7 * * ? – Fire every 2 minutes starting at 7:46am and ending at 7:58am, every day

Let’s improve our CronExpressionsExample and add new methods to schedule jobs according to the above crone expressions.

CronExpressionsExample:

package com.javacodegeeks.quartz;

import org.quartz.CronScheduleBuilder;
import org.quartz.DateBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;

public class CronExpressionsExample {
	private static final String GROUP_NAME = "CroneExamples";	
	
	// Fire at current time + 1 min every day
	public static Trigger fireAfterAMinEveryDayStartingAt(int startHr, int startMin, int startSec, int nowHr, int nowMin) {
		Trigger trigger = TriggerBuilder.newTrigger()
				.withIdentity("fireAfterAMinStartingAt", GROUP_NAME)
				.startAt(DateBuilder.todayAt(startHr, startMin, startSec))
				.withSchedule(cronSchedule("Fire every day starting at (" + startHr + ":" + startMin + ":" + startSec + "), start the job in a min from now",
						"0 " + (nowMin + 1) + " " + nowHr + " * * ? *"))		
				.build();
		return trigger;
	}
	// Fire at 10:15am every day during the year 2015
	public static Trigger fireAt1015MinEveryDayDuring2015() {
		Trigger trigger = TriggerBuilder.newTrigger()
				.withIdentity("fireAt1015MinEveryDayDuring2015", GROUP_NAME)
				.withSchedule(cronSchedule("Fire at 10:15am every day during the year 2015",
						"0 0 15 10 * * 20015"))		
				.build();
		return trigger;
	}
	
	// Fire between 10AM and 3PM every day
	public static Trigger fireBetween10To3EveryDay() {
		Trigger trigger = TriggerBuilder.newTrigger()
				.withIdentity("fireBetween10To3EveryDay", GROUP_NAME)
				.withSchedule(cronSchedule("Fire between 10AM and 3PM every day",
						"0 0 10-15 * * ?"))		
				.build();
		return trigger;
	}
	
	// Fire between 10AM and 3PM on weekends SAT-SUN
	public static Trigger fireBetween10to3OnWeekends() {
		Trigger trigger = TriggerBuilder.newTrigger()
				.withIdentity("fireBetween10to3OnWeekends", GROUP_NAME)
				.withSchedule(cronSchedule("Fire between 10AM and 3PM on weekends SAT-SUN",
						"0 0 10-15 * * SAT-SUN"))		
				.build();
		return trigger;
	}
	
	// Fire only on certain days of month (14,18 and 21)
	public static Trigger fireOnlyOnCertainDaysInMonth() {
		Trigger trigger = TriggerBuilder.newTrigger()
				.withIdentity("fireOnlyOnCertainDaysInMonth", GROUP_NAME)
				.withSchedule(cronSchedule("Fire only on certain days of month",
						"0 0 10 14,18,21 * ?"))		
				.build();
		return trigger;
	}

	//Fire every 2 minutes starting at 7:46am and ending at 7:58am, every day
	public static Trigger fireAfterTwoMinFrom7_46To7_58() {
		Trigger trigger = TriggerBuilder.newTrigger()
				.withIdentity("fireAfterTwoMinFrom7_46To7_58", GROUP_NAME)
				.withSchedule(cronSchedule("Fire only on certain days of month",
						"0 46/2 7 * * ?"))		
				.build();
		return trigger;
	}

	private static CronScheduleBuilder cronSchedule(String desc, String cronExpression) {
		System.out.println(desc + "->(" + cronExpression + ")");
		return CronScheduleBuilder.cronSchedule(cronExpression);
	}
}

Let’s try running one of the cron trigger. In QuartzSchedulerCronExpressionExample, we don’t shutdown scheduler explicitly and let it run indefinitely so that it can run jobs scheduled at different times.

13. Run the Cron Expression

We will now try running CronExpressionsExample.fireAfterTwoMinFrom7_46To7_58(). Change your system time to 46 mins and then run the example so that the scheduler picks up the job. The cron expression 0 46/2 7 * * ? will fire the job every 2 minutes starting at 7:46am and ending at 7:58am, every day. We will just try for today :-), obviously.

QuartzSchedulerCronExpressionsExample:

package com.javacodegeeks.quartz;

import java.util.Date;

import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;


public class QuartzSchedulerCronExpressionExample {
	public static void main(String[] args) throws Exception {	
		QuartzSchedulerCronExpressionExample quartzSchedulerExample = new QuartzSchedulerCronExpressionExample();
		quartzSchedulerExample.fireJob();
	}
	
	public void fireJob() throws SchedulerException, InterruptedException {
		SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
		Scheduler scheduler = schedFact.getScheduler();
		scheduler.start();
		
		// define the job and tie it to our HelloJob class
		JobBuilder jobBuilder = JobBuilder.newJob(MyJob.class);
		
		JobDetail jobDetail = jobBuilder.usingJobData("example", "com.javacodegeeks.quartz.QuartzSchedulerListenerExample")	
				.withIdentity("myJob", "group1")
				.build();
	
		System.out.println("Current time: " + new Date());				
		
		// Tell quartz to schedule the job using our trigger
		// Fire at current time + 1 min every day
		scheduler.scheduleJob(jobDetail, CronExpressionsExample.fireAfterTwoMinFrom7_46To7_58());
	}
}

You can see the job starts at Wed Sep 16 07:48:00 IST 2015. It fires job every 2 mins. The job firs 6 times. The last output statement has the next schedule time which is Thu Sep 17 07:46:00 IST 2015, that is, next day.

Output:

Current time: Wed Sep 16 07:46:24 IST 2015
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Current time: Wed Sep 16 07:46:24 IST 2015
Fire every 2 minutes starting at 7:46am and ending at 7:58am, every day->(0 46/2 7 * * ?)
--------------------------------------------------------------------
MyJob start: Wed Sep 16 07:48:00 IST 2015
Example name is: com.javacodegeeks.quartz.QuartzSchedulerListenerExample
MyJob end: -1, key: group1.myJob
MyJob next scheduled time: Wed Sep 16 07:50:00 IST 2015
--------------------------------------------------------------------
Job count 1
--------------------------------------------------------------------
MyJob start: Wed Sep 16 07:50:00 IST 2015
Example name is: com.javacodegeeks.quartz.QuartzSchedulerListenerExample
MyJob end: -1, key: group1.myJob
MyJob next scheduled time: Wed Sep 16 07:52:00 IST 2015
--------------------------------------------------------------------
Job count 2
--------------------------------------------------------------------
MyJob start: Wed Sep 16 07:52:00 IST 2015
Example name is: com.javacodegeeks.quartz.QuartzSchedulerListenerExample
MyJob end: -1, key: group1.myJob
MyJob next scheduled time: Wed Sep 16 07:54:00 IST 2015
--------------------------------------------------------------------
Job count 3
--------------------------------------------------------------------
MyJob start: Wed Sep 16 07:54:00 IST 2015
Example name is: com.javacodegeeks.quartz.QuartzSchedulerListenerExample
MyJob end: -1, key: group1.myJob
MyJob next scheduled time: Wed Sep 16 07:56:00 IST 2015
--------------------------------------------------------------------
Job count 4
--------------------------------------------------------------------
MyJob start: Wed Sep 16 07:56:00 IST 2015
Example name is: com.javacodegeeks.quartz.QuartzSchedulerListenerExample
MyJob end: -1, key: group1.myJob
MyJob next scheduled time: Wed Sep 16 07:58:00 IST 2015
--------------------------------------------------------------------
Job count 5
--------------------------------------------------------------------
MyJob start: Wed Sep 16 07:58:00 IST 2015
Example name is: com.javacodegeeks.quartz.QuartzSchedulerListenerExample
MyJob end: -1, key: group1.myJob
MyJob next scheduled time: Thu Sep 17 07:46:00 IST 2015
--------------------------------------------------------------------
Job count 6

14. Download the Eclipse Project

This was an example about Quartz Scheduler Cron Expressions.

Download
You can download the full source code of this example here: cronExpressionsExample.zip

Ram Mokkapaty

Ram holds a master's degree in Machine Design from IT B.H.U. His expertise lies in test driven development and re-factoring. He is passionate about open source technologies and actively blogs on various java and open-source technologies like spring. He works as a principal Engineer in the logistics domain.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button