This should be really easy. I\'m using Quartz running under Apache Tomcat 6.0.18, and I have a jobs.xml file which sets up my scheduled job that runs every minute.
W
If you are using org.springframework.scheduling.quartz.QuartzJobBean
:
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
try {
Scheduler scheduler = context.getScheduler();
List<JobExecutionContext> jobs = scheduler.getCurrentlyExecutingJobs();
for (JobExecutionContext job : jobs) {
if (job.getTrigger().equals(context.getTrigger()) && job.getJobDetail() != context.getJobDetail()) {
LOG.warn("Ignored!");
return;
}
}
...
} catch (SchedulerException e) {
LOG.error("What a luck! :'(", e);
}
...
}
could you set the job as a StatefulJob, and for each trigger you create set the MisfireInstruction for the job to not fire if it is missed? Not sure what type of job you are using but you'll have to do some research into the misfireInstructions that are available for your trigger type.
Thanks, D
dimitrisli's answer is not complete so here's mine.
When Quartz Job wakes up it returns its JobExecutionContext to you. I assume you want to skip jobs with the same trigger.
List<JobExecutionContext> jobs = jobExecutionContext.getScheduler().getCurrentlyExecutingJobs();
for (JobExecutionContext job : jobs) {
if (job.getTrigger().equals(jobExecutionContext.getTrigger()) && !job.getJobInstance().equals(this)) {
logger.info("There's another instance running, so leaving" + this);
return;
}
}
We get currently job contexts and check if there's a previous job instance with the same trigger. If this is the case we just skip with return.
when your Quartz job wakes up you can do:
JobDetail existingJobDetail = sched.getJobDetail(jobName, jobGroup);
if (existingJobDetail != null) {
List<JobExecutionContext> currentlyExecutingJobs = (List<JobExecutionContext>) sched.getCurrentlyExecutingJobs();
for (JobExecutionContext jec : currentlyExecutingJobs) {
if(existingJobDetail.equals(jec.getJobDetail())) {
//String message = jobName + " is already running.";
//log.info(message);
//throw new JobExecutionException(message,false);
}
}
//sched.deleteJob(jobName, jobGroup); if you want to delete the scheduled but not-currently-running job
}
There is another simpler solution. The job can be given an annotation of DisallowConcurrentExecution which prevents multiple concurrent instances running. See docs here.
The link keeps breaking so here is the relevant sample.
@DisallowConcurrentExecution
public class ColorJob implements Job {
I accomplished something similar making my job classes implement StatefulJob, which ensures that no other jobs starts before the current running job finishes.
Hope that helps ;)
PD: I implemented it using JBoss... but I don't think that makes any difference.