Quartz Simple Trigger Example

0

Triggers are used to trigger the execution of jobs. The most common types of triggers are simple triggers and cron triggers. In this article, we will look into simple triggers. In order to schedule a job, we build the trigger and associate it to a job. We use simple trigger if our needs are very basic, for example, if we want to execute the job just once at a specific moment of time or repeat the job execution at a specific interval for certain number of times.

Trigger Key

A trigger is identified by its key which is a combination of trigger name and group. If a trigger already exists with the same name and group,quartz scheduler will throw exception org.quartz.ObjectAlreadyExistsException.
Jobs and triggers can also be placed into ‘groups’, groups help organizing them into categories, for example, high performance jobs or reporting jobs. If we don’t want to categorize then automatically they will be placed into the default group Scheduler.DEFAULT_GROUP.

TriggerBuilder

In order to build the trigger use the quartz provided TriggerBuilder class. TriggerBuilder follows domain specific language style and provides a fluent API. It also makes sure that the trigger is updated with reasonable defaults in case certain we haven’t set all the necessary information. For example, if the trigger name is not specified then a unique name will be generated.
Below is an example where a trigger is built with minimum information.

TriggerBuilder
.newTrigger()
.build();

Here is an example where we even tune its schedule.

TriggerBuilder
.newTrigger()
.withIdentity("dupTrigger", "group")
.startNow()
.withSchedule(simpleSchedule()
              .withIntervalInSeconds(5)
              .withRepeatCount(2))
.build();

SchedulerBuilder

SimpleTrigger instances execute a job at a specific moment and repeat after a specific interval based schedules which repeat for certain count or indefinitely. The interval and repeat settings are managed using SimpleScheduleBuilder thus triggers are built using TriggerBuilder for the trigger’s main properties and SimpleScheduleBuilder for the SimpleTrigger specific properties like the interval and repeat count.

Trigger Builder

Trigger Builder

Simple Trigger Window

SimpleTrigger include the following properties.

  1. Start Time – The startTime property indicates when the trigger’s schedule first comes into effect.
  2. End Time – The endTime property indicates when the trigger’s schedule should no longer be in
    effect. Rather than having to compute the number of times it would repeat
    between the start-time and the end-time, you can simply specify the end-time and then
    use a repeat count of REPEAT_INDEFINITELY
  3. Interval
  4. Repeat Count – The repeat count can be zero, a positive integer, or the constant value
    SimpleTrigger.REPEAT_INDEFINITELY. The repeat interval property must be zero, or a
    positive long value, and represents a number of milliseconds.
Trigger Window

Trigger Window

Build the Triggers

Let’s now build couple of triggers.

  1. fireAfterEvery5SecondsRepeatThrice() – Starts using current time, fires after an interval of 5 seconds and repeats thrice.
  2. fireOnce20SecondsFromNow() – Starts at 20 seconds later from now. Fires only once.

Triggers:

package com.javarticles.quartz;

import static org.quartz.DateBuilder.futureDate;
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;

import static org.quartz.DateBuilder.IntervalUnit.*;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;

public class Triggers {

    public static Trigger fireAfterEvery5SecondsRepeatThrice() {
        SimpleTrigger trigger = TriggerBuilder
                .newTrigger()
                .withIdentity("trigger1", "group")
                .startNow()
                .withSchedule(simpleSchedule()
                                .withIntervalInSeconds(5)
                                .withRepeatCount(2))
                .build();
        return trigger;
    }
    
    public static Trigger fireOnce20SecondsFromNow() {
        SimpleTrigger trigger = TriggerBuilder
                .newTrigger()
                .withIdentity("trigger2", "group")
                .startAt(futureDate(20, SECOND))
                .withSchedule(simpleSchedule())
                .build();
        return trigger;
    }
}

Create a Simple Job

Job simply prints the trigger name and decrements the count of the latch, if available.

SimpleJob:

package com.javarticles.quartz;

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

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

public class SimpleJob implements Job {

    public SimpleJob() {
    }

    public void execute(JobExecutionContext context) throws JobExecutionException {
        JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
        String triggerName = (String) jobDataMap.get("triggerName");
        System.out.println("Tigger " + triggerName + ", fired at " + new Date());
        CountDownLatch c = (CountDownLatch) jobDataMap.get("countDown");
        c.countDown();
    }

}

Simple Trigger Example

In the example, we create a scheduler and starts it. Next we associate the job with a trigger. We set a latch against the trigger and with each fire the count of the latch is decremented. Once all the triggers are fired, we then try with our next trigger.

QuartzTriggerExample:

package com.javarticles.quartz;

import java.util.concurrent.CountDownLatch;
import java.util.logging.Logger;

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

public class QuartzTriggerExample {
    public static void main(String[] args) throws SchedulerException {
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        Scheduler scheduler = schedulerFactory.getScheduler();
        scheduler.start();
        try {            
            CountDownLatch c = new CountDownLatch(3);
            JobDataMap jobDataMap = new JobDataMap();
            jobDataMap.put("triggerName", "fireAfterEvery5SecondsRepeatThrice");
            jobDataMap.put("countDown", c);
            JobDetail jobDetail = JobBuilder.newJob(SimpleJob.class)
                    .usingJobData(jobDataMap)
                    .withIdentity("job1", "group").build();
            LOGGER.info("start trigger " + jobDataMap.getString("triggerName"));
            scheduler.scheduleJob(jobDetail, Triggers.fireAfterEvery5SecondsRepeatThrice());            
            try {
                c.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
            c = new CountDownLatch(1);
            jobDataMap = new JobDataMap();
            jobDataMap.put("triggerName", "fireOnce20SecondsFromNow");
            jobDataMap.put("countDown", c);
            jobDetail = JobBuilder.newJob(SimpleJob.class)
                    .usingJobData(jobDataMap)
                    .withIdentity("job2", "group").build();  
            LOGGER.info("start trigger " + jobDataMap.getString("triggerName"));
            scheduler.scheduleJob(jobDetail, Triggers.fireOnce20SecondsFromNow());
            try {
                c.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        } finally {
            try {
                scheduler.shutdown();
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        }

    }
    
    private static Logger LOGGER = Logger.getLogger(QuartzTriggerExample.class.getSimpleName());
}

Output:

17:40| INFO | StdSchedulerFactory.java 1184 | Using default implementation for ThreadExecutor
17:40| INFO | SimpleThreadPool.java 268 | Job execution threads will use class loader of thread: main
17:40| INFO | SchedulerSignalerImpl.java 61 | Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
17:40| INFO | QuartzScheduler.java 240 | Quartz Scheduler v.2.2.1 created.
17:40| INFO | RAMJobStore.java 155 | RAMJobStore initialized.
17:40| 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.

17:40| INFO | StdSchedulerFactory.java 1339 | Quartz scheduler 'DefaultQuartzScheduler' initialized from default resource file in Quartz package: 'quartz.properties'
17:40| INFO | StdSchedulerFactory.java 1343 | Quartz scheduler version: 2.2.1
17:40| INFO | QuartzScheduler.java 575 | Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.
Mar 25, 2016 5:40:57 PM com.javarticles.quartz.QuartzTriggerExample main
INFO: start trigger fireAfterEvery5SecondsRepeatThrice
Tigger fireAfterEvery5SecondsRepeatThrice, fired at Fri Mar 25 17:40:57 IST 2016
Tigger fireAfterEvery5SecondsRepeatThrice, fired at Fri Mar 25 17:41:02 IST 2016
Tigger fireAfterEvery5SecondsRepeatThrice, fired at Fri Mar 25 17:41:07 IST 2016
Mar 25, 2016 5:41:07 PM com.javarticles.quartz.QuartzTriggerExample main
INFO: start trigger fireOnce20SecondsFromNow
Tigger fireOnce20SecondsFromNow, fired at Fri Mar 25 17:41:27 IST 2016
17:41| INFO | QuartzScheduler.java 694 | Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutting down.
17:41| INFO | QuartzScheduler.java 613 | Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED paused.
17:41| INFO | QuartzScheduler.java 771 | Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutdown complete.

Download the source code

This was an example about Quartz SimpleTrigger.

You can download the source code here: quartzTriggerExample.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 [email protected]

Comments are closed.