Stop single quartz scheduler - java

I have 5 different quartz schedulers which implement 5 different jobs. If I am stopping one scheduler, remaining schedulers are getting stopped. Why?

I'm pretty sure your actually creating references to the same Scheduler, you need to give each scheduler a different "SchedulerName". At the moment it looks like each time your creating a new scheduler its defaulting the SchedulerName.
The "job executor" is actually not the SchedulerFactoryBean. It is the Scheduler bean(to be precise calling its start method invokes the aggregated QuartzScheduler.start method which fires the Trigger-s), provided by the SchedulerFactoryBean. As a matter of fact this Scheduler is stored(and looked-up) under the schedulerName(which if not explicitly set has the same default value for every configured SchedulerFactoryBean) in the SchedulerRepository singleton(SchedulerRepository.getInstance()).
That's how unless you set a different schedulerName for your SchedulerFactoryBean-s, you will always get the same scheduler by each and every SchedulerFactoryBean-s
http://forum.springsource.org/showthread.php?40945-Multiple-Quartz-SchedulerFactoryBean-instances
I know this refers to Spring Beans but i still think the same applies here.

Related

Using #DisallowConcurrentExecution in Quartz scheduler

I am sorry if this question is too naive,
I am expecting the jobs to be scheduled so that it executes one by one, and not parallely.It is executed only once.
From docs, #DisallowConcurrentExecution is
An annotation that marks a {#link Job} class as one that must not have multiple instances executed concurrently (where instance is based-upon a {#link JobDetail} definition - or in other words based upon a {#link JobKey}).
But when I schedule a job with same JobKey, I am getting
Failed to schedule a job org.quartz.ObjectAlreadyExistsException
If I generate a different JobKey, it is not heeding to #DisallowConcurrentExecution and the job is getting executed in parallel(as mentioned in docs).
Please suggest how can I achieve this, any pointers would really help!
PS: I do not know the jobs that would be scheduled. So, I need some method to dynamically link up the jobs,if the job is already running.
Same JobKey = same job.
Different JobKey = different job.
Quartz won't let you use the same JobKey more than once because that'd be two jobs with the same key. Like having two users with the same ID.
What you need to do is schedule different JobTriggers for the same JobKey.
#DisallowConcurrentExecution avoids overlapping executions of the same job. If you use a different JobKey, it's not the same job anymore, so the annotation doesn't have any effect. But for a given JobKey with several JobTriggers, #DisallowConcurrentExecution will keep the triggers from launching a new execution of the job, if the previous one hasn't finished yet.
I suggest having a look at Quartz's documentation to get a deeper understanding of the above concepts.

Quartz scheduler clustered

I'm trying to understand how quartz scheduler works in a clustered environment. I believe pointing the multiple instances of the scheduler app to the same DB and also setting isClustered=true will make sure only one scheduler fires the job at the same time. However, I have the following questions:
Who ensures that only one scheduler executes the job and how?
Can two scheduler instances have the same name (ids are auto, so I guess they will be distinct? (org.quartz.scheduler.instanceName = MyScheduler)
Who sets DB parameters like next fire time?
Ideally, should any of the 11 or so predefined tables (QRTZ_TRIGGERS) be populated? Or they are populated based on the beans in the application upon on app startup?

Re-scheduling a task that executes once using Spring Trigger

I have a requirement where I need to schedule a task (from UI) that will execute only once. After completion, I should be able to re-schedule (from UI) the same task again.
I know #Schedule won't work here as I need to execute only once. So after further searching I am able to schedule the task to execute only once at specific time using TaskScheduler with Runnable and Date and also along with #Async. However I am unable to make it reschedule.
Looks like using quartz might be possible, but I haven't gone through it yet.
Is it possible to implement my requirement with Spring Trigger. I can see only two implementation of trigger interface CronTrigger and PeriodicTrigger.
Please suggest any possible approaches.
Including initial piece of code would be helpful.
The easiest way I see would be to create a regularly scheduled "trigger" method in a Spring bean that checks a certain condition and only executes the "real" action when the condition is met (e.g. the time you entered in the UI is in the past and the job has not started yet):
#Scheduled(fixedDelay = 5000)
public void trigger() {
if(condition){
//... do the action
}
}
This requires some persistence to store the "job metadata" like the execution date and the current state of the job, but that seems "lighter" than working with threads or including quartz just for this one use case.

how many triggers can a single instance of SchedulerFactory have?

My application may fire around 1000's or more triggers everyday. Each of these is categorized into 4 categories:
morning(9am)
afternoon(1pm)
evening(6pm)
night(10pm)
And at each of these times, there will be 100's of trigger fired. Below is code
SchedulerFactory schdFact = new StdSchedulerFactory();
Scheduler schd;
for(ecah morningSchedulers){
// some logic for instantiating trigger
AbstractTrigger trigger = (AbstractTrigger) newTrigger().withSchedule(cronSchedule("0 0"+mAlert+"0,0,0 * * ?")).build();
trigger.setStartTime(strtDat);
trigger.setEndTime(endDat);
final JobDetail job = newJob(AlertJob.class).build();
schd.scheduleJob(job, trigger);
}
I have 2 questions here
Should I instantiate scheduler inside for loop or outside and schedule many triggers to the same scheduler. i.e. schd = schdFact.getScheduler(); where should I write this line?(inside or outside for loop)
I have to reschedule some of these triggers. i.e. stop on some condition and start again.
how many triggers can a single instance of SchedulerFactory have?
There is a similar question in the official FAQ:
How many jobs is Quartz capable of running?
This is a tough question to answer... the answer is basically "it depends". [...] So, the limiting factor of the number of Triggers and Jobs Quartz can "store" and monitor is really the amount of storage space available to the JobStore (either the amount of RAM or the amount of disk space).
Also remember about this:
[...] The actual number of jobs that can be running at any moment in time is limited by the size of the thread pool. If there are five threads in the pool, no more than five jobs can run at a time.
If you have thousands of triggers (you aren't confusing triggers and trigger executions?), consider JDBC storage. But if you have only few triggers but running several times a day, RAM store is enough.
Should I instantiate scheduler inside for loop or outside and schedule many triggers to the same scheduler
Definitely have only a single scheduler for the whole application. It is rare to have more than one scheduler in an application, see: Utilizing Multiple (Non-Clustered) Scheduler Instances.
Create the scheduler once and treat as a singleton.
I have to reschedule some of these triggers. i.e. stop on some condition and start again.
This is, again, explained in the documentation: Updating an existing Trigger. Basically you need to know the trigger key:
// retrieve the trigger
Trigger oldTrigger = sched.getTrigger(triggerKey("oldTrigger", "group1");
// obtain a builder that would produce the trigger
TriggerBuilder tb = oldTrigger.getTriggerBuilder();
// update the schedule associated with the builder, and build the new trigger
// (other builder methods could be called, to change the trigger in any desired way)
Trigger newTrigger = tb.withSchedule(simpleSchedule()
.withIntervalInSeconds(10)
.withRepeatCount(10)
.build();
sched.rescheduleJob(oldTrigger.getKey(), newTrigger);
BTW if just want to run a job at a given single hour, there is an easier API. Instead of:
newTrigger().
withSchedule(
cronSchedule("0 0"+mAlert+"0,0,0 * * ?")
).
build()
You can simply say:
newTrigger().
withSchedule(
dailyAtHourAndMinute(mAlert, 42)
).
build();
Have a look at Lesson 6: CronTrigger of the official tutorial.

How to execute more then one method of a spring bean on app startup

I have a spring bean with 4 blocking queues. Each queue is assigned a method (named processQueueX() ) which calls take() on that queue and processes taken object from queue.
I want to call each of those method in a separate thread on app startup.
I tried with task scheduler and fixed-delay setting but that in some way blocks tomcat and it stops responding to requests. Each method needs to be called once, so scheduling was a bad idea I guess.
Init method does not work also since it works in a single thread, each method has endless loop to process queue forever.
Is there a way to call these methods declaratively from spring config file in manner similar to task namespace? Or programmatically?
Tnx
I think using scheduler not a bad idea use quart scheduler with simple trigger thus quarz will do threading for you and tomcat not effected .And configure quartz with just enough number of thread.
Would 23.4. The Spring TaskExecutor abstraction help?
Where the example has a MessagePrinterTask class, you would have similar, but your run() method would access one of the queues. You would set up your Spring config to inject one of the queues into the task, so depending on how similar your queues are, you might be able to use the same Runnable task.

Categories