Quartz 2 Scheduler Pass Parameters to Job with JobDataMap using @PersistJobDataAfterExecution and @DisallowConcurrentExecution Example
May 22, 2015
In this page we will walk through Quartz 2 scheduler passing parameters to Job with JobDataMap using @PersistJobDataAfterExecution and @DisallowConcurrentExecution example. We can pass any number of parameters to the job scheduled by Quartz. To play this role, Quartz provides JobDataMap which is a map in which we can put values as key/value pair. JobDataMap is obtained from JobDetail. In job class implementing Job interface, we access JobDataMap using JobExecutionContext of execute() method. @PersistJobDataAfterExecution and @DisallowConcurrentExecution are annotated at job class. @PersistJobDataAfterExecution enables JobDataMap to update data while execution and allows to re-store it after execution. To avoid concurrent execution, we must annotate our job class with @DisallowConcurrentExecution. We will discuss here complete example step by step.
JobDataMap
org.quartz.JobDataMap is used to put and get values for a job instance. If the job is annotated with@PersistJobDataAfterExecution
, then after job execution job states are re-persisted. JobDataMap
is used to pass parameters to scheduled job. Using JobDetail
instance we get the instance of JobDataMap
and then add the values which needs to pass to scheduled job.
JobDataMap jobDataMap= jobDetail.getJobDataMap() jobDataMap.put(PrintNameJob.NAME, "RAM");
JobDataMap
values, we can do as follows.
JobDataMap dataMap = context.getJobDetail().getJobDataMap(); String name = dataMap.getString(NAME);
JobDetail
instance by JobExecutionContext
and get the instance of JobDataMap
using JobDetail
instance.
@PersistJobDataAfterExecution and @DisallowConcurrentExecution Annotations
@PersistJobDataAfterExecution annotation which is clear by its name, is used onJob
implementing class to update JobDataMap
while execution and can re-store it after execution. While doing such task, concurrent execution should be avoided. So we must also annotate our class with @DisallowConcurrentExecution annotation.
Create a Job
For the demo, we are creating a job in which we will access two parameters fromJobDataMap
passed while scheduling the job, one is the name and another is count. While execution, we will update count and persist it again in JobDataMap
. In every execution of job, the new instance of job is created. To check it, I have taken a member variable with the value "new object" and within execution we have changed its value. What we see in output is that this will always be "new object", means every time, new instance of job is created.
PrintNameJob.java
package com.concretepage.job; import org.quartz.DisallowConcurrentExecution; import org.quartz.Job; import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.JobKey; import org.quartz.PersistJobDataAfterExecution; @PersistJobDataAfterExecution @DisallowConcurrentExecution public class PrintNameJob implements Job { public static final String NAME = "name"; public static final String COUNT = "count"; private String flag = "new object"; @Override public void execute(JobExecutionContext context) throws JobExecutionException { JobDataMap dataMap = context.getJobDetail().getJobDataMap(); //fetch parameters from JobDataMap String name = dataMap.getString(NAME); int count = dataMap.getInt(COUNT); JobKey jobKey = context.getJobDetail().getKey(); System.out.println(jobKey+": "+ name+"-"+count+": flag="+flag); count++; //add next counter to JobDataMap dataMap.put(COUNT, count); flag= "object changed"; } }
Run Scheduler with passing parameters to Job
We will create two job details and trigger for the demo and will be added to scheduler for race condition. Both will access the same job for 3 rounds with 5 seconds time interval. We will pass two parameters, name and count with different values usingJobDataMap
.
PassParameterByJobDataMap.java
package com.concretepage; import java.util.Calendar; import java.util.Date; 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; import com.concretepage.job.PrintNameJob; public class PassParameterByJobDataMap { public static void main(String[] args) throws SchedulerException { SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); //create first JobDetail and Trigger JobDetail jobDetail = JobBuilder.newJob(PrintNameJob.class).withIdentity("ramjob", "ourgroup").build(); SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity("ramtrigger", "ourgroup") .startAt(new Date(Calendar.getInstance().getTimeInMillis()+ 5000)) .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5) .withRepeatCount(3)).build(); //add passing parameters to JobDataMap for first JobDetail jobDetail.getJobDataMap().put(PrintNameJob.NAME, "RAM"); jobDetail.getJobDataMap().put(PrintNameJob.COUNT, 11); scheduler.scheduleJob(jobDetail, trigger); //create second JobDetail and Trigger jobDetail = JobBuilder.newJob(PrintNameJob.class).withIdentity("rahimjob", "ourgroup").build(); trigger = TriggerBuilder.newTrigger().withIdentity("rahimtrigger", "ourgroup") .startAt(new Date(Calendar.getInstance().getTimeInMillis()+ 5000)) .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5) .withRepeatCount(3)).build(); //add passing parameters to JobDataMap for second JobDetail jobDetail.getJobDataMap().put(PrintNameJob.NAME, "RAHIM"); jobDetail.getJobDataMap().put(PrintNameJob.COUNT, 21); scheduler.scheduleJob(jobDetail, trigger); scheduler.start(); try { //wait for 30 seconds to finish the job Thread.sleep(30000); } catch (InterruptedException e) { e.printStackTrace(); } //shutdown scheduler gracefully scheduler.shutdown(true); } }
ourgroup.ramjob: RAM-11: flag=new object ourgroup.rahimjob: RAHIM-21: flag=new object ourgroup.ramjob: RAM-12: flag=new object ourgroup.rahimjob: RAHIM-22: flag=new object ourgroup.ramjob: RAM-13: flag=new object ourgroup.rahimjob: RAHIM-23: flag=new object ourgroup.ramjob: RAM-14: flag=new object ourgroup.rahimjob: RAHIM-24: flag=new object