Im trying to execute the following quartz scheduler code in the a cluster environment.
scheduler.unscheduleJob("genericJobTrigger", "DEFAULT");
where as
Scheduler scheduler = (Scheduler) context.getBean("scheduler");
JobDetail genericJob = (JobDetail) context.getBean("genericJob");
CronTrigger genericJobTrigger = (CronTrigger) context.getBean("genericJobTrigger");
Above piece of code is deleting entries from trigger and job detail. It supposed to remove only trigger right?
Why Quartz scheduler's unscheduleJob is deleting both trigger and job detail?
durability is set true to Jobs to avoid deleting the JOBS when Triggers are deleted.
Whenever you are creating an object of JobDetail then set storeDurably(), refer the below example:
return JobBuilder.newJob(ScheduledJob.class)
.setJobData(jobDataMap)
.withDescription("job executes at specified frequency")
.withIdentity(UUID.randomUUID().toString(), "email-jobs")
.storeDurably() //This will not allow to delete automatially
.build();
Also you can verify it by checking the value of IS_DURABLE column in jobDetails table.
Related
I want to fetch the lastJobExecution with specific job parameter.
Scenario:
I want to store userEmail as a job parameter, and then fetch last job execution of that user :
Map<String, JobParameter> parameters = new HashMap<>();
parameters.put("userEmail", new JobParameter("something#xyz.com", true));
JobParameters jobParameters = new JobParameters(parameters);
jobRepository.getLastJobExecution("jobName", jobParameters)
Issue in above approach:
If I only use put only userEmail as a job parameter, same user wont be able to trigger another job once previous job is finished, as error: A job instance already exists with given job parameters.
So I am planning to add userEmail + startTime as job parameter. So same user can trigger multiple jobs.
However, now I want to fetch last job execution of that user, I need both userEmail + startTime
Map<String, JobParameter> parameters = new HashMap<>();
parameters.put("userEmail", new JobParameter("something#xyz.com", true));
parameters.put("startTime", new JobParameter(123L, true));
JobParameters jobParameters = new JobParameters(parameters);
jobRepository.getLastJobExecution("jobName", jobParameters)
But I dont have startTime when fetching last job execution of that user.
Is there any way to fetch last job execution with only 1 job parameter?
Or do I need to write my own JdbcTemplate-based DAO implementation to run the select query ?
Tried using long way, like fetch all job executions by job name and then filter.
But this is quite inefficient way.
Identifying job parameters are hashed together to produce a key that is used to identify job instances. So there is no direct way to fetch the last job execution of a job instance with a single parameter. You need to fetch is yourself with a custom SQL query or programmatically by filtering job executions as you did.
That said, it feels like this a job parameters design issue, rather than a limitation in Spring Batch. The choice of start time a job parameter is not suitable to your case as it is not constant in time, hence you can't have it when fetching the last job execution. You need to find a way to uniquely identify job instances which allows you to have all information needed when fetching executions.
I am using below code to get the all Job Details and display them in my UI. But it is taking too long ( Around 35 seconds ) to fetch the job details ( around 150 Quartz jobs ) from QUARTZ using JDBC data store ( Oracle DB).
Is there any alternate ways to speed up the task?
Any API support available for pagination from Quartz?
//All below code can be written using Java 8 Streams as well. Broke down the code to understand which //operation is taking time
Scheduler scheduler = schedulerFactoryBean.getScheduler();
Set<TriggerKey> triggerKeys = scheduler.getTriggerKeys(GroupMatcher.triggerGroupEquals(groupName)); //groupName - my group name - filtering by groupname
Iterator iterator = triggerKeys .iterator();
//This while block is taking around 12 seconds for around 150 jobs
while(iterator.hasNext()){
TriggerKey triggerKey = (TriggerKey) iterator.next();
if(scheduler.getTriggerState(triggerKey).equals(TriggerState.NONE)){
iterator.remove();
}
Map<TriggerKey, MyPOJO> myJobMap = new HashMap();
//This for loop is taking around 22 seconds for around 150 jobs
for(TriggerKey key : triggerKeys){
Trigger trigger = scheduler.getTrigger(key);
JobDataMap jobDataMap = scheduler.getJobDetail(trigger.getJobKey()).getJobDataMap();
MyPOJO myPOJO = jobDataMap.get("MYJOBPOJO");
myJobMap.put(key, myPOJO);
}
I have gone through the Quartz documentation but did not find any specific details on how to improve this read operation performance
I have job that will run every 10 mins. I don't want to use Spring Scheduler based on last job run next job will schedule to run. Suppose First job ran at 10:15 AM, Subsequent job needs to run at 10:25 AM. When i googled i saw posts with nextExecutionTime. When i use nextExecutionTime my subsequent job is running at 10:20 instead of 10:25. Below is my code, Can any one give an idea how i can run my job at exact 10 mins from last run.
CronTrigger trigger = new CronTrigger("0 0/10 * * * ?");
SimpleTriggerContext triggerContext = new SimpleTriggerContext();
triggerContext.update(Date.from(ZonedDateTime.now().toInstant()), Date.from(ZonedDateTime.now().toInstant()), Date.from(ZonedDateTime.now().toInstant()));
Date nextFireAt = trigger.nextExecutionTime(triggerContext);
System.out.println(nextFireAt);
Can you try the below. I provide below the sequence.
Get the date now.
Add 10 mins to the date and get a new updated date
Update the like triggerContext.update(null, null, date in which you have added 10 mins);
I have a Quartz Job that I can schedule with some Cron Trigger.
ReportSchedule reportSchedule = ... // my object
JobDetail jobDetail = new JobDetail(reportSchedule.getScheduleName(),
reportSchedule.getScheduleGroup(),
ExtendedReportJob.class /* my job */);
jobDetail.getJobDataMap().put("reportSchedule", reportSchedule);
jobDetail.setDescription(reportSchedule.getScheduleDescription());
CronTrigger trigger = ...; // depends on the report schedule
scheduler.scheduleJob(jobDetail, trigger);
This code successfully writes the job and details to a database.
The reportSchedule object contains specific parameters that are required for the job. However, I may want to change the parameters.
I can do this with
scheduler.deleteJob(name, group);
scheduler.scheduleJob(jobDetail, trigger);
// where jobDetail.getJobDataMap() has the updated reportSchedule
Doing this, however, will trigger the job right away since the trigger depends on the report schedule and I don't want to change it (I want to keep original date). So my question: Is there any way to modify the JobDetail or JobDataMap between jobs without changing the Trigger?
I'm using Quartz 1.6.0.
The solution is simple enough, just have to know the API.
The Scheduler class has the following method
Scheduler#addJob(JobDetail, boolean);
In which the passed JobDetail will overwrite the previous one if the boolean argument is set to true.
So
// name and group are the primary key of the job detail
final JobDetail jobDetail = new JobDetail(name, group, ExtendedReportJob.class);
// reportSchedule is the object I've previously modified
jobDetail.getJobDataMap().put(ORStatics.REPORT_SCHEDULE, reportSchedule);
jobDetail.setDescription(reportSchedule.getScheduleDescription());
// overwrite the previous job, however retaining the triggers
scheduler.addJob(jobDetail, true);
will update the job detail in persistent storage. Since the primary key for the table containing the JobDetail will remain the same, we don't need to change the triggers. They will still execute it as scheduled.
What about getting the trigger with getTrigger(String triggerName, String triggerGroup) and store it in a variable. Then create a new job with your new jobDataMap and use the old trigger?
What is the best way to disable a job in the JDBCJobStore without deleting it's job or trigger records and without wiping the cron expression?
Use scheduler.pauseJob() or scheduler.pauseTrigger().
Alternatively you can use the following SQL script:
UPDATE QRTZ_TRIGGERS SET TRIGGER_STATE = "PAUSED"
Use the pauseJob or pauseJobGroup methods of JobStore.