2

I have been working on a scheduler engine which reads schedule Jobs from a database and schedules them which works fine however the rows in the database are just "Configuration" of certain types of job for example:

A Certain Configuration to get FTP has

host: imagineryHost1.com 
post: 22

and another of the same class has

host: imagineryHost2.com
post: 21

We create two FPTjob's with their own triggers and their own separate data.

/**
BaseJob is an Abstract class extending QuartzJobBean used to handle our logging and 
other requirements that need across all our jobs.
*/
public class FTPJob extends BaseJob {

    /**
        Called from executeInternal of QuartzJobBean 
    */
    @Override
    public boolean execute1V(JobExecutionContext context) {
        //Code to get Files from FTP.
    }
}

These are scheduled using the TriggerBuilder with a cron.

If i add @DisallowConcurrentExecution is will only allow 1 instance of our FTPJob to run at any one time, However I need to to be able to run Multiple instance of FTPJob but limit it to only one instance of that particular configuration of that class.

Any leads on how to progress will be highly appreciated :)

UPDATE

Based on ftom2's answer I went digging and found TriggerListener since every job configuration has it own uniqueID it possible i could "Veto" the job from running ie.

public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) {
    try {
        Iterator<JobExecutionContext> it =     
        context.getScheduler().getCurrentlyExecutingJobs().iterator();

        boolean found = false;
        while(it.hasNext()) {
            JobExecutionContext job = it.next();

            if(trigger.getJobKey().equals(job.getJobDetail().getKey())) {
                return false;
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Is there any other way that is a little more built in to handle this?

Patrick
  • 1,717
  • 7
  • 21
  • 28
AbstractChaos
  • 4,211
  • 1
  • 19
  • 28

3 Answers3

1

I'm not sure if it is possible but this might be a direction.

You can implement a JobListener and then do the following:

  1. using jobWasExecuted you will set a flag in the jobDetails that this job finished.
  2. using jobToBeExecuted, you will check job status before it starts and see if it is in running state, if yes - stop it (see here), if no - let it run and set its state to running.

Hope this helps.

Community
  • 1
  • 1
Tomer
  • 17,787
  • 15
  • 78
  • 137
  • Thanks for your answer it lead me to the update i added to question, One problem that may arise is the requirement for data persitence for your flag to be maintained but that could work. I will leave this open for rest of day to see if any others to find alternative solutions if not i will mark this as answer :) – AbstractChaos Jun 27 '12 at 10:44
  • the jobDetails is used to persist data, is it not enough for you? – Tomer Jun 27 '12 at 11:07
  • By JobDetails I assumed you mean set the value in the JobDataMap within it, However anything put back into that map is not recorded unless you set the [PersistJobDataAfterExecution](http://quartz-scheduler.org/api/2.0.0/org/quartz/PersistJobDataAfterExecution.html) and my only point was that in some cases that may not be desirable :) – AbstractChaos Jun 27 '12 at 11:15
0

Sorry to jump in a year late... but would the suggested use of TriggerLinstener not be non-thread-safe? Seems to me that two jobs can pass the veto stage before any of them will be returned by getCurrentlyExecutingJobs(). In the same situation I used an execution lock on the scheduler, which is even less "built-in"... (the idea is - try get lock in the trigger linstener, veto if cannot, return lock from job listener jobWasExecuted).

Gilly
  • 1
0

Looks like the stateful jobs are not allowed to execute concurrently, you may simply implements the StatefulJob instead of Job interface

Bai
  • 108
  • 1
  • 5
  • Thanks for your answer however while a particular instance (where data is the same) of that job cannot be run twice an instance of the class itself can assuming the data is different. – AbstractChaos May 22 '14 at 08:42