Updating CroneSchedule & Job Dynamically without stopping server - java

I need help in externalizing the below cron schedule or executing it dynamically. For example, in the below code it is hardcoded to perform every Saturday: cronSchedule("0 0 12 ? * SAT"). I want the value inside the cronSchedule() to externalize so that even after the server is started, I can still change the cron schedule to Monday or every day based on my choice and it can be run. I am looking for suggestion in java and not in spring.
public void run() throws Exception {
// Getting a reference to a scheduler
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sched = sf.getScheduler();
// job will run every week at Saturday 12 Noon Server Time
JobDetail job = newJob(CachingJob.class).withIdentity("job1", "group1").build();
CronTrigger trigger = newTrigger().withIdentity("trigger1", "group1").withSchedule(cronSchedule("0 0 12 ? * SAT"))
.build();
Date ft = sched.scheduleJob(job, trigger);
sched.start();
SchedulerMetaData metaData = sched.getMetaData();
}
Any input or suggestion is appreciated.

We can perform below method to reschedule the job :
cronScheduler.rescheduleJob(cronTrigger.getKey(), newTrigger().withIdentity("customTrigger", "defaultGroup")
.withSchedule(cronSchedule(cronExpression)).build());

Related

how to delete specific trigger for a scheduled job

i have created job with like creating with one jobName and different keys(see JobDataMap)
CronTriggerImpl trigger = new CronTriggerImpl();
JobDetailImpl jobDetail = null;
trigger.setMisfireInstruction(CronTrigger.MISFIRE_INSTRUCTION_DO_NOTHING);
trigger.setName(getUniqueJobId());
trigger.setCronExpression(cronExpression);
trigger.setTimeZone(timeZone);
JobDataMap dataMap = new JobDataMap();
dataMap.put("jobName", "job");
dataMap.put("id", "key");
trigger.setJobDataMap(jobDataMap);
jobDetail = new JobDetailImpl();
jobDetail.setName(getUniqueJobId());
jobDetail.setJobDataMap(jobDataMap);
jobDetail.setJobClass(JobLauncherDetails.class);
scheduler.scheduleJob(jobDetail, trigger);
it is working properly but i want to delete the specific trigger how can i delete
i had seen fee source but those are not matching. please help me out
**Updated : **
i want to delete like
schedule.deleteJob(JobKey) what will be the job key as per my schedule configuration
or should i use schedule.unScheduler()
org.quartz.Scheduler#unscheduleJob accepts the trigger key as parameter. Hence, you can remove the trigger specified, not the job.
public static boolean removeJob(String jobName, String jobGroup) throws SchedulerException {
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
if (scheduler.checkExists(triggerKey)) {
scheduler.unscheduleJob(triggerKey); // trigger + job
}
logger.info(">>>>>>>>>>> removeJob success, triggerKey:{}", triggerKey);
return true;
}
Hope that helps.
UPDATE:
We don't know actually your functional need. But, you can create Trigger in cleaner way and bind it to a given Job:
CronTrigger trigger = TriggerBuilder.newTrigger()
  .withIdentity("trigger3", "group1")
  .withSchedule(CronScheduleBuilder.cronSchedule("0 0/2 8-17 * * ?"))
  .forJob("myJob", "group1") // Binding the Trigger to the Job
  .build();
I see you are using JobDataMap in your Trigger. This is useful for passing parameters to a Job that are specific to the executions of the trigger. Do you need really that?
Useful link: https://www.baeldung.com/quartz

Unable to store job because one already exists with this identification

I'm new with Quartz.
I succeeded to install it and run it.
But I have an error when I run it for the second time because the job already exists with this identification.
Here my code :
public void scheduleJobs() throws Exception {
try {
int i = 0;
scheduler = new StdSchedulerFactory().getScheduler();
JobKey job1Key = JobKey.jobKey("job"+i, "my-jobs"+i);
JobDetail job1 = JobBuilder
.newJob(SimpleJob.class)
.withIdentity(job1Key)
.build();
TriggerKey tk1 = TriggerKey.triggerKey("trigger"+i, "my-jobs"+i);
Trigger trigger1 = TriggerBuilder
.newTrigger()
.withIdentity(tk1)
.withSchedule(CronScheduleBuilder.dailyAtHourAndMinute(11, 25))
.build();
scheduler.start(); // start before scheduling jobs
scheduler.scheduleJob(job1, trigger1);
i++;
printJobsAndTriggers(scheduler);
} catch (SchedulerException e) {
LOG.error("Error while creating scheduler", e);
}
}
I tried to use an integer i to change the name but it does not work.
Do you have any idea how can I fix it?
Many thanks.
You can:
check if the "job key" already exists, and remove the existing job before creating a new one:
scheduler.deleteJob(job1Key);
or create a new job with another key (in your case, each time you execute scheduleJobs(), variable i has the same value (0)
or just re-use the same job (why would you create a new job if the old one is still good)
or use the RAM Job Store, which does not persist jobs in database (each time you will use your software, you will have an empty job store)
It really depends on what you want to do with your jobs!
Check for existing job before scheduling:
JobDetail job;
SimpleTrigger trigger;
//Create your trigger and job
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
if (scheduler.checkExists(job.getKey())){
scheduler.deleteJob(job.getKey());
}
scheduler.scheduleJob(job, trigger);
This is not a direct answer to the specific code listed in the question, but I didn't notice it when searching elsewhere and thought this might be useful for future readers:
If you're in a situation where you have an existing Job but just want to add a new Trigger, you can call:
scheduler.ScheduleJob(trigger);
and it will add the Trigger to the Job without trying to recreate the Job. The only trick is that you have to make sure the Trigger's JobKey is correct.
My overall code for this interaction looks roughly like:
IJobDetail job; // Handed in
ITrigger trigger; // Handed in
// Keeping track of this because we need to know later whether it's new or not
var newJob = job == null;
if (newJob)
{
job = JobBuilder.Create<TargetJob>()
.WithIdentity([whatever])
[.OtherConfiguration()]
.Build();
}
var trigger = TriggerBuilder
.Create()
.WithIdentity([whatever])
// ** Gotcha #1: Make sure it's linked to the job **
.ForJob(job.Key)
[.OtherConfiguration()]
.Build();
if (newJob)
{
_scheduler.ScheduleJob(job, trigger);
}
else
{
// ** Gotcha #2: Make sure you don't reschedule the job **
_scheduler.ScheduleJob(trigger);
}
If anyone of you are facing the same issue and your solution is in C#. This is how you can fix this error.
This is where we configure the scheduler.
public async Task StartAsync(CancellationToken cancellationToken) {
try {
var scheduler = await GetScheduler();
var serviceProvider = GetConfiguredServiceProvider();
scheduler.JobFactory = new CustomJobFactory(serviceProvider);
await scheduler.Start();
await ConfigureDailyJob(scheduler);
}
catch(Exception ex) {
_logger.Error(new CustomConfigurationException(ex.Message));
}
}
This is how we can configure the Job, please be noted that we are checking whether the job is already there, and if the await scheduler.CheckExists(dailyJob.Key) returns true, we delete that job info and create a new one with the same key.
private async Task ConfigureDailyJob(IScheduler scheduler) {
var dailyJob = GetDailyJob();
if (await scheduler.CheckExists(dailyJob.Key)) {
await scheduler.DeleteJob(dailyJob.Key);
_logger.Info($ "The job key {dailyJob.Key} was already existed, thus deleted the same");
}
await scheduler.ScheduleJob(dailyJob, GetDailyJobTrigger());
}
There are the supporting private functions.
private IJobDetail GetDailyJob() {
return JobBuilder.Create < IDailyJob > ().WithIdentity("dailyjob", "dailygroup").Build();
}
private ITrigger GetDailyJobTrigger() {
return TriggerBuilder.Create().WithIdentity("dailytrigger", "dailygroup").StartNow().WithSimpleSchedule(x = >x.WithIntervalInHours(24).RepeatForever()).Build();
}
You can get the complete source code from this GitHub repository.
You can create new jobs by taking i as a static int. And instead of "job"+i it would be "job"+ Integer.toString(i) . It worked for me.

Cron trigger not firing for the specified timezone

I have list of timezones; and for each timezone, I have to start schedule job. Following is the code
cronexpr = 0 30 8,12,15,17 * * ?
if(cronexpr != null){
for(int i=0;i<tList.size();i++) {
job = new JobDetailImpl("runSMSJob"+i,"SMSJobgrp"+i,SMSJob.class);
trigger = new CronTriggerImpl("runMeJobTesting"+i, "group", "runSMSJob"+i, "SMSJobgrp"+i, cronexpr, tList.get(i));
logger.info("TIMEZONE is "+trigger.getTimeZone());
schd.start();
schd.scheduleJob(job, trigger);
}
Here tList is a list containing several timezones. On my local system its running properly but on server where the timezone is BST, even though the locale is India timezone, it's firing at the BST time.
Do any one have any idea on why its failing to take the specified timezone properly?

Quartz CronTrigger executing jobs on wrong date/time

I am using following cron expression to execute a job on every Friday at specified time of day (in sample below it's 1:13 PM).
0 13 13 ? * FRI
So expected behaviour should be if I initialize this trigger any day other then Friday then it should not start executing until next Friday. But whats happening in my case is even if I initialized this trigger today (as today is Wednesday), it starts executing jobs at the very moment.
Relevant java source:
CronTrigger cronTrigger = new CronTrigger("trigger_" + groupName, groupName, cronExpression);
cronTrigger.setStartTime(startDate); //startDate = 1-Mar-2012
cronTrigger.setEndTime(endDate); //endDate = 30-Apr-2012
Your issue is configuring the startTime. startTime is meant to be the time at at which the trigger should occur. Since the date is old this causes a misfire in the scheduler and the default behavior is for the scheduler to immediately refire.
Remove setStartTime, the default behavior is for startTime to be set to the current time and the first trigger time will be the match to the cron trigger after the start time so this Thursday.
Quick little test I through together to verify:
public class Test {
public static void main(String[] args) throws ParseException, SchedulerException {
String groupName = "group";
String cronExpression = "0 13 13 ? * THUR";
CronTrigger cronTrigger = new CronTrigger("trigger_" + groupName, groupName, cronExpression);
cronTrigger.setStartTime(new Date(0));
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
JobDetail detail = new JobDetail("testJob", groupName, TestJob.class);
scheduler.scheduleJob(detail, cronTrigger);
scheduler.start();
try {
Thread.sleep(50001);
} catch (Exception ignore) {
}
}
public static class TestJob implements Job {
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("TEST");
}
}
}
When removing the setStartTime my print message does not trigger. With it there the print message triggers.

Quartz jobs not running

Working with Java Quartz, I was able to schedule one job. Then I tried something like the following code to be able to add an other job. Now neither seems to trigger at the defined time. What am I doing wrong?
I want to use approach like following, not xml configuration.
scheduler = StdSchedulerFactory.getDefaultScheduler();
JobDetail jobFull = new JobDetail("job1", "group1", IntegrationJobFull.class);
JobDetail jobPartial = new JobDetail("job2", "group1", IntegrationJobPartial.class);
CronTrigger triggerFull = new CronTrigger("trigger1", "group1", "job1", "group1", "0 15 3 * * ?");
CronTrigger triggerPartial = new CronTrigger("trigger2", "group1", "job2", "group1", "* 0,30 * * * ?");
scheduler.addJob(jobFull, false);
scheduler.addJob(jobPartial, false);
scheduler.scheduleJob(triggerFull);
scheduler.scheduleJob(triggerPartial);
scheduler.start();
The JobDetails created above are non-durable, this means that the addJob method will fail. Use the overloaded scheduleJob method to associate the job and the trigger.
Remove the addJob and scheduleJob calls and replace with:
scheduler.scheduleJob(jobFull, triggerFull);
scheduler.scheduleJob(jobPartial, triggerPartial);
Also * has been specifed the seconds field for trigger2. This will mean that the job will be triggered every second for the specified minutes. I'm not sure if that was the intention.
The desired cron expression may be:
"0 0,30 * * * ?"

Categories

Resources