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
Related
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());
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.
I try to pass parameters using quartz(1.6) api in ServletA
JobDataMap map = new JobDataMap();
map.put("date", "20151101");
scheduler = new StdSchedulerFactory().getScheduler();
scheduler.triggerJob(jobName, groupName, map);
When I trigger JobA, it work.
But I can't get parameter in JobA from folloing code.
map is null.
JobDataMap map = jobExecutionContext.getJobDetail().getJobDataMap();
String date = (String) map.get("date");
Do I miss something important?? Thanks for help.
Parameter maps can be passed to the execution from the job or/and the trigger. In your solution you explicitely try to get the job's datamap (at ctx.getJobDetail().getJobDataMap()) , which is null because you set your parameters via the trigger.
You can use the getMergedJobDataMap of JobExecutionContext to get a parameter map merged from both:
JobDataMap map = jobExecutionContext.getMergedJobDataMap();
String date = (String) map.get("date");
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 * * * ?"
I have a Quartz job written in Java which runs fine if I have the Quartz JobDetail line set as follows:
JobDetail jd = new JobDetail("FeedMinersJob", scheduler.DEFAULT_GROUP, FeedMinersScheduler.class);
But I would like to dynamically load the class because the job details are stored in a database table. So I want something like this:
JobDetail jd = new JobDetail(sj.getJobName(), scheduler.DEFAULT_GROUP, sj.getJobClassFile());
Where sj is a scheduled job object and method sj.getJobClassFile() returns the name of the class defined in sj instead of having the class name hardcoded.
I've tried permutations of the Java Class.forName method but without success.
I ran into the same issue.
It does not output anything, and does not throw an error either.
This is because your job class doesn't have an empty constructor. So even though the code is correct, it has no mechanism to create the job object.
If you add an empty constructor to your Job class, itwill work.
As I understand it, you code should like this:
Class<?> jobClass = Class.forName(sj.getJobClassFile());
JobDetail jd = new JobDetail(sj.getJobName(), scheduler.DEFAULT_GROUP, jobClass);
Can you please post the code snippets which didn't work?
Try this
try {
Class<?> jobClass = Class.forName(sj.getJobClassFile());
JobDetail jd = new JobDetail(sj.getJobName(), scheduler.DEFAULT_GROUP, jobClass);
} catch (ClassNotFoundException e) {
// put here some error handling
}
And if it doesn't work please give more details about the problem - compilation error, exception in runtime or some other problem.
I have this, maybe it will be usefull to you: (getClassName() returns a string)
Class<?> jobClass = Class.forName(t_job.getClassName());
if (Job.class.isAssignableFrom(jobClass)) {
// create a job detail that is not volatile and is durable (is persistent and exists without trigger)
JobDetail job = new JobDetail(t_job.getName(), t_job.getGroupName(), jobClass, false, true, true);
job.setDescription(t_job.getDescription());
}