Sunday, 10 December 2017

Trigger Quartz Job Immediately.

Quartz Trigger Job Immediately In Java.


In this post, we will focus on how to fire the Quartz job immediately.


Quartz scheduler fire a new job immediately


There are multiple ways of firing the quartz job immediately, lets see few approaches here,

Approach 1: 
In this approach, we will create the quartz job and fire it immeditely.

package com.javabypatel.demo.service;

import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.scheduling.quartz.QuartzJobBean;

public void scheduleAndStartJob(String jobName, String jobGroup) {

 //Create a new Job 
 JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
 JobDetail job = JobBuilder.newJob(YourJobClass.class).withIdentity(jobKey).storeDurably(true).build();

 Scheduler scheduler = schedulerFactoryBean.getScheduler();
 try {
  //Register this job to the scheduler   
  scheduler.addJob(job, true);

  //Start a Job      
  scheduler.triggerJob(jobKey);
 } catch (SchedulerException e1) {
  e1.printStackTrace();
 }
}


YourJobClass.java
package com.javabypatel.demo.job;

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

public class SimpleJobTemp implements Job{
 
 @Override
 public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
  JobKey key = jobExecutionContext.getJobDetail().getKey();
  System.out.println("Simple Job started with key :" + key.getName() + ", Group :"+key.getGroup() + " , Thread Name :"+Thread.currentThread().getName());
 }

}

Approach 2:
In this approach, we will fire already created quartz job immeditely.
package com.javabypatel.demo.job;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
 
public void fireJob(String jobName, String jobGroup) {
 System.out.println("Request received to scheduleJob");

 JobKey jobKey = JobKey.jobKey(jobName, jobGroup);

 // Get scheduler factory
 Scheduler scheduler = schedulerFactoryBean.getScheduler();
 try {
  //Fire the job now   
  scheduler.triggerJob(jobKey);
 } catch (SchedulerException e) {
  e.printStackTrace();
 }
}


Approach 3:
In this approach, for firing the job immediately, we just need to update the job time with the time now and Quartz scheduler will execute it now. Code for this approach is present in sample project. 

Check updateOneTimeJob() and updateCronJob() method in JobServiceImpl.java


Below you will get detailed example on,
How to Create, Edit, Start, Stop, Pause, Resume, Delete Quart Job both Simple as well as Cron Job with sample Project.

Spring Boot and Quartz Scheduler in Action.


Download complete source code of Quartz Scheduler with Spring Boot example using below link,
https://github.com/javabypatel/spring-boot-quartz-demo 

Example uses,
  1. Spring Boot 1.5.7
  2. Quartz 2.2.3
  3. PostgreSQL 9.4.1208
  4. Angular2
Application provides Sample UI using which you can,
  1. Schedule Simple Quartz Job.
  2. Schedule Cron Quartz Job.
  3. Pause Quartz Job.
  4. Resume Quartz Job
  5. Edit Quartz Job. 
  6. Delete Quartz Job.
  7. Unschedule Quartz Job. 
  8. Stop Quartz Job.
  9. Check if Job is currently Running.
  10. Get the current state of Quartz Job.
  11. Get the list of all Scheduled Jobs.
  12. Job and Trigger Listeners for doing any operations before and after job starts, Listeners also hels in taking any action in case of job misfires due to application shutdown etc.

Quartz Scheduler Working.


Quartz work on concept of Jobs and Triggers. 
  1. Job is anything that need to be executed when event occurs. 
  2. Trigger is basically a event which contains time as when this event should occur.
JOB is binded by TRIGGER. when trigger event occurs it executes associated job.

There are 2 types of trigger,
  1. Simple Trigger
  2. Cron Trigger
Simple Trigger:  SimpleTrigger is used if you need to execute job exactly once at a specific moment in time, or at a specific moment in time followed by repeats at a specific interval.

For example, if you want the trigger to fire at exactly 11:23:54 AM on January 13, 2015, or if you want it to fire at that time, and then fire five more times, every ten seconds.


Cron Trigger:  CronTrigger is often more useful than SimpleTrigger, It is used for scheduling jobs having complex time like if you need to execute job that recurs based on calendar-like notions, rather than on the exactly specified intervals.

With CronTrigger, you can specify firing-schedules such as "every Friday at noon", or "every weekday and 9:30 am", or even "every 5 minutes between 9:00 am and 10:00 am on every Monday, Wednesday and Friday during January".


In Sample application we will demonstrate below features using Quartz library.
 
package com.javabypatel.demo.service;

import java.util.Date;
import java.util.List;
import java.util.Map;

import org.springframework.scheduling.quartz.QuartzJobBean;

public interface JobService {
 boolean scheduleOneTimeJob(String jobName, Class<? extends QuartzJobBean> jobClass, Date date);
 boolean scheduleCronJob(String jobName, Class<? extends QuartzJobBean> jobClass, Date date, String cronExpression);
 
 boolean updateOneTimeJob(String jobName, Date date);
 boolean updateCronJob(String jobName, Date date, String cronExpression);
 
 boolean unScheduleJob(String jobName);
 boolean deleteJob(String jobName);
 boolean pauseJob(String jobName);
 boolean resumeJob(String jobName);
 boolean startJobNow(String jobName);
 boolean isJobRunning(String jobName);
 List<Map<String, Object>> getAllJobs();
 boolean isJobWithNamePresent(String jobName);
 String getJobState(String jobName);
 boolean stopJob(String jobName);
}


Demo application also explains Quartz listeners, 

There are 2 types of listeners in quartz.
  1. Quartz Job Listeners.
  2. Quartz Trigger Listeners.
Listeners are callback methods that executes on events.

If you want to perform any task before job starts or when job completes or when trigger got misfired due to application shutdown, Quartz listeners will be helpful.


Download complete source code from here


Quartz Scheduler + Spring Boot + Angular2 Project Setup in Eclipse.


  1. Download the project from github.
  2. Import the project in Eclipse using "Import" > "Existing Maven Project".
  3. Once import is done properly and all dependencies are downloaded, project will look like below,


Running application in your Environment


After setting project in Eclipse,
  1. Install PostgreSQL database.(If you are planning to use other database then make respective changes in pom.xml for loading driver and in application.properties file for providing database path)

  2. Create database name "quartzdemoapp" (if you want to use any other name then give the same database name in application.properties file by replacing "quartzdemoapp" by that name)

  3. Open command prompt in admin mode.

  4. Go to "ui-app" folder and execute "npm install" command as shown below, (Make sure you have node and npm installed.)

  5. Go to "ui-app" folder and execute "npm run server" command as shown below,

    This step will start server and ui-app will be deployed.

  6. Open the browser and hit http://localhost:8080/ you will see the application UI as shown above which will be used to schedule both simple and cron quartz job.

  7. Start the Spring-boot application by clicking on "SpringBootQuartzAppApplication.java" > Right click, Run as, "Java Application"
    Note: Server will be hosted on localhost and port as 7080. (
    http://localhost:7080/)
Note:
Client application is listening on port 8080 and Server application is listening on port 7080.

If you don't want to run 2 application separately, then transpile the typescript files to javascript and put those files in your web application as shown below,

For converting typescript files to javascript files,
  1. Open command prompt, navigate to ui-app folder and run "npm run build".
  2. After above step you will see "target" folder created inside "ui-app" folder, copy those files to your web application and run the server application.

Configuration files.


There are 3 configuration files,
  1. application.properties
  2. data.sql
  3. quartz.properties

application.properties :
It contains configuration for server and database as shown below,
server.port=7080 //Server will be listening on port 7080
spring.application.name=Scheduledemo

####### SPRING JPA ############
spring.jpa.database=POSTGRESQL
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create-drop
####### SPRING JPA ############

####### POSTGRES ############
spring.datasource.driver-class-name=org.postgresql.Driver

#create the database by name "quartzdemoapp", here I am using postgresql running on port 5432.
#if you want other database, change the url.
spring.datasource.url=jdbc:postgresql://localhost:5432/quartzdemoapp 

#put your database username below
spring.datasource.username=postgres 

#put your database password below
spring.datasource.password=admin    


####### POSTGRES ############


data.sql :
Quartz require jobs and triggers to be stored in database. 
data.sql contains SQL scripts that creates tables required by quartz to manage scheduler.

quartz.properties :
org.quartz.scheduler.instanceName=springBootQuartzApp
org.quartz.scheduler.instanceId=AUTO
org.quartz.threadPool.threadCount=5 //number of concurrent jobs that can be run.
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
org.quartz.jobStore.useProperties=true
org.quartz.jobStore.misfireThreshold=60000 //if job is delayed by 1 minute, don't consider it as misfire.
org.quartz.jobStore.tablePrefix=qrtz_ //prefix used for all quartz related tables
org.quartz.jobStore.isClustered=false
org.quartz.plugin.shutdownHook.class=org.quartz.plugins.management.ShutdownHookPlugin
org.quartz.plugin.shutdownHook.cleanShutdown=TRUE


Pass parameters to Quartz Job.


If you want to pass any custom data/parameters to Quartz job that you can used at the the time of job execution, You can use JobDataMap class.

There are two types of data that you can set while job creation,
  1. Primitive data types, OR 
  2. User defined objects
Note: It would be good practice to store primitive data types in JobDataMap to avoid object serialization issues.

For storing instance variable,
Class MyClass{
 String temp;
}

MyClass obj = new MyClass();
obj.temp = "sample data";
 
Scheduler scheduler = schedulerFactoryBean.getScheduler();
scheduler.getContext().put("myobject", obj);

For storing primitive types,
You can modify createJob method as shown below for storing key-value pairs.
protected static JobDetail createJob(){
 JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();

 // set job data map
 if(jobDataMap!=null && jobDataMap.size()>0){
  JobDataMap jobDataMap = new JobDataMap();
  jobDataMap.put("myKey", "myValue");
  factoryBean.setJobDataMap(jobDataMap);
 }
 factoryBean.afterPropertiesSet();
 return factoryBean.getObject();
}

You can access the same data/parameters at the time of job execution as shown below,
For retrieving stored key-value pairs.
JobDataMap dataMap = jobExecutionContext.getMergedJobDataMap();
String myValue = dataMap.getString("myKey");
System.out.println("Value:" + myValue);

For retrieving stored object, It will try to deserialize the bytes Object.
SchedulerContext schedulerContext = null;
try {
 schedulerContext = jobExecutionContext.getScheduler().getContext();
} catch (SchedulerException e1) {
 e1.printStackTrace();
}
MyClass yourClassObject = (MyClass) schedulerContext.get("myobject");

You may also like to see


Compress a given string in-place and with constant extra space.

Check whether a given string is an interleaving of String 1 and String 2.

Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence from beginWord to endWord.

Serialize and Deserialize a Binary Tree

Advanced Multithreading Interview Questions In Java

Enjoy !!!! 

If you find any issue in post or face any error while implementing, Please comment.

No comments:

Post a Comment