Quartz – Enterprise Open Source Job Scheduler – Part1

 

In this post, we will discuss the java job scheduler called “Quartz”. In a brief introduction, quartz is providing job scheduling infrastructure to integrate with standalone applications to large enterprise applications, to perform the defined tasks on scheduling basis.

                  The use case to use Quartz is any task which is performing on a regular interval of time. For example, in an e-commerce application, if you have a job to process the inventory feed on a daily basis, then we can create a Quartz job to trigger the task.

                  Quartz can be integrated as part of any standalone application, any servlet container, via RMI or as a cluster of stand-alone programs (with load-balance and fail-over capabilities). We can create persistence jobs or in-memory jobs.

                  Now, we will see how we can create a simple job to send emails to all users on a daily basis. Before that, we will see how to set up a development environment to use Quartz.

  1. As a first step, download the most recent stable release from http://www.quartz-scheduler.org/downloads/ . In this example, I am using Quartz 2.1.7.

  2. After downloading, unpack the zip file. The unpacked Quartz package contains a number of jar files, located under the root directory. The main Quartz library is named quartz-all-2.1.7.jar. This jar includes all the Quartz features.

  3. Keep the quartz-all-2.1.7.jar into our application classpath.

  4. Keep all the dependent jar files (slf4j-log4j12-1.6.1.jar,slf4j-api-1.6.1.jar,log4j-1.2.16.jar,javax.transaction.jar,c3p0-0.9.1.1.jar) into the class path.

  5. Keep quartz.properties file in class path.

All the configuration details will be available under quartz.properties file. So, the Quartz scheduler will take the configuration details from here.

                Now, we will create a standalone Java application to demonstrate the Quartz. The source code is available here https://github.com/2013techsmarts/Quartz_Proj

The sample code creates a scheduler instance is given below.

package com.smarttechies.scheduler;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.impl.StdSchedulerFactory;
public class MailScheduler {
/**
* @param args
*/
public static void main(String[] args) {
try {
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler scheduler = sf.getScheduler();
scheduler.start();
} catch (SchedulerException se) {
   se.printStackTrace();
   }
 }
}

We are getting scheduler instance by calling org.quartz.impl.StdSchedulerFactory.getDefaultScheduler method. We are starting the scheduler by calling the start method. When we start the scheduler, it will get the configuration from the quartz.properties available in the classpath.

The log will depict some of the scheduler details.

2013-04-19 22:18:42 INFO  StdSchedulerFactory:1175 - Using default implementation for ThreadExecutor
2013-04-19 22:18:42 INFO  SchedulerSignalerImpl:61 - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
2013-04-19 22:18:42 INFO  QuartzScheduler:243 - Quartz Scheduler v.2.1.7 created.
2013-04-19 22:18:42 INFO  RAMJobStore:154 - <strong>RAMJobStore</strong> initialized.
2013-04-19 22:18:42 INFO  QuartzScheduler:268 - Scheduler meta-data: Quartz Scheduler (v2.1.7) '<strong>MailScheduler</strong>' 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 3 threads.
Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.
2013-04-19 22:18:42 INFO  StdSchedulerFactory:1324 - Quartz scheduler 'MailScheduler' initialized from default file in current working dir: 'quartz.properties'
2013-04-19 22:18:42 INFO  StdSchedulerFactory:1328 - Quartz scheduler version: 2.1.7
2013-04-19 22:18:42 INFO  QuartzScheduler:534 - Scheduler MailScheduler_$_NON_CLUSTERED started.

From the log, we can understand that scheduler is using quartz.properties and we have configured in-memory scheduler. So, it is using RAM job store.

Now, we create a job and trigger to run the job every minute. To create a job, we need to implement org.quartz.Job interface and provide implementation to the execute method.

The sample MailSenderJob code is given below.

package com.smarttechies.job;
import org.apache.log4j.Logger;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class MailSenderJob implements Job{
Logger log = Logger.getLogger(MailSenderJob.class);
@Override
public void execute(JobExecutionContext pArg0) throws JobExecutionException {
log.info("The mail sender job triggerd");
//From here call the mail sender service
  }
 }

Now, in the MailScheduler code which was written earlier, we need to configure the job and the trigger. After the change, the MailScheduler code will be as shown below.

package com.smarttechies.scheduler;
import java.text.ParseException;
import org.quartz.CronExpression;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.impl.JobDetailImpl;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.triggers.CronTriggerImpl;
import com.smarttechies.job.MailSenderJob;
public class MailScheduler {
/**
 * @param args
 * @throws ParseException
*/
public static void main(String[] args) throws ParseException {
try {
  SchedulerFactory sf = new StdSchedulerFactory();
  Scheduler scheduler = sf.getScheduler();
  //Tie the MailSenderJob to scheduler
  JobDetailImpl jobDetail = new JobDetailImpl();
  jobDetail.setGroup("group1");
  JobKey jobKey = new JobKey("job1");
  jobDetail.setKey(jobKey);
  jobDetail.setJobClass(MailSenderJob.class);
  //create a trigger and tie it to the job
  // Trigger the job to run on every minute
  CronExpression cronExpression = new CronExpression("0 0/1 * 1/1 * ? *");
  CronTriggerImpl cronTrigger = new CronTriggerImpl();
  cronTrigger.setName("mail trigger");
  cronTrigger.setCronExpression(cronExpression);
  //Tie the job and the trigger to the scheduler
  scheduler.scheduleJob(jobDetail, cronTrigger);
  scheduler.start();
} catch (SchedulerException se) {
  se.printStackTrace();
    }
  }
}

The above scheduler will trigger the job every minute. The log indicates the same.

2013-04-20 11:26:11 INFO  StdSchedulerFactory:1175 - Using default implementation for ThreadExecutor
2013-04-20 11:26:11 INFO  SchedulerSignalerImpl:61 - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
2013-04-20 11:26:11 INFO  QuartzScheduler:243 - Quartz Scheduler v.2.1.7 created.
2013-04-20 11:26:11 INFO  RAMJobStore:154 - RAMJobStore initialized.
2013-04-20 11:26:11 INFO  QuartzScheduler:268 - Scheduler meta-data: Quartz Scheduler (v2.1.7) 'MailScheduler' 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 3 threads.
Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.
2013-04-20 11:26:11 INFO  StdSchedulerFactory:1324 - Quartz scheduler 'MailScheduler' initialized from default file in current working dir: 'quartz.properties'
2013-04-20 11:26:11 INFO  StdSchedulerFactory:1328 - Quartz scheduler version: 2.1.7
2013-04-20 11:26:11 INFO  QuartzScheduler:534 - Scheduler MailScheduler_$_NON_CLUSTERED started.
2013-04-20 11:27:00 INFO  <strong>MailSenderJob:14 - The mail sender job triggerd</strong>

To stop the scheduler, we need to call the shutDown method on the scheduler.

The approach we followed in this article to configure the job and trigger is programmatic.  In the coming post, we will see, how we can improve the same code by moving the job and trigger configurations to an XML file by using quartz plugins.

Advertisement

Siva Janapati is an Architect with experience in building Cloud Native Microservices architectures, Reactive Systems, Large scale distributed systems, and Serverless Systems. Siva has hands-on in architecture, design, and implementation of scalable systems using Cloud, Java, Go lang, Apache Kafka, Apache Solr, Spring, Spring Boot, Lightbend reactive tech stack, APIGEE edge & on-premise and other open-source, proprietary technologies. Expertise working with and building RESTful, GraphQL APIs. He has successfully delivered multiple applications in retail, telco, and financial services domains. He manages the GitHub(https://github.com/2013techsmarts) where he put the source code of his work related to his blog posts.

Tagged with: , ,
Posted in Quartz Scheduler, Scheduler

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

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

Dzone.com
DZone

DZone MVB

Java Code Geeks
Java Code Geeks
OpenSourceForYou
%d bloggers like this: