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.
What I would like to do, is if the job is still running when the next trigger time rolls around, I don't want to start a new job, so I can let the old instance complete.
Is there a way to specify this in jobs.xml (prevent concurrent instances)?
If not, is there a way I can share access to an in-memory singleton within my application's Job implementation (is this through the JobExecutionContext?) so I can handle the concurrency myself? (and detect if a previous instance is running)
update: After floundering around in the docs, here's a couple of approaches I am considering, but either don't know how to get them to work, or there are problems.
Use StatefulJob. This prevents concurrent access... but I'm not sure what other side-effects would occur if I use it, also I want to avoid the following situation:
Suppose trigger times would be every minute, i.e. trigger#0 = at time 0, trigger #1 = 60000msec, #2 = 120000, #3 = 180000, etc. and the trigger#0 at time 0 fires my job which takes 130000msec. With a plain Job, this would execute triggers #1 and #2 while job trigger #0 is still running. With a StatefulJob, this would execute triggers #1 and #2 in order, immediately after #0 finishes at 130000. I don't want that, I want #1 and #2 not to run and the next trigger that runs a job should take place at #3 (180000msec). So I still have to do something else with StatefulJob to get it to work the way I want, so I don't see much of an advantage to using it.
Use a TriggerListener to return true from vetoJobExecution().
Although implementing the interface seems straightforward, I have to figure out how to setup one instance of a TriggerListener declaratively. Can't find the docs for the xml file.
Use a static
shared thread-safe object (e.g. a semaphore or whatever) owned by my class that implements Job.
I don't like the idea of using singletons via the static
keyword under Tomcat/Quartz, not sure if there are side effects. Also I really don't want them to be true singletons, just something that is associated with a particular job definition.
Implement my own Trigger which extends SimpleTrigger and contains shared state that could run its own TriggerListener.
Again, I don't know how to setup the XML file to use this trigger rather than the standard <trigger><simple>...</simple></trigger>
.
It has no built-in UI for configuration or monitoring, no useful and reasonably searchable logging or historical review, no support for multiple execution nodes, no administration interface, no alerts or notifications, not to mention buggy recovery mechanisms for failed jobs and missed jobs.
If you want to schedule multiple jobs in your console application you can simply call Scheduler. ScheduleJob (IScheduler) passing the job and the trigger you've previously created: IJobDetail firstJob = JobBuilder. Create<FirstJob>() .
deleteJob(jobKey(<JobKey>, <JobGroup>)); This method will only interrupt/stop the job uniquely identified by the Job Key and Group within the scheduler which may have many other jobs running. scheduler. shutdown();
Quartz scheduler allows an enterprise to schedule a job at a specified date and time. It allows us to perform the operations to schedule or unschedule the jobs. It provides operations to start or stop or pause the scheduler. It also provides reminder services.
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 {
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With