Quartz : Dynamic job scheduling - java

I'm scheduling quartz job dynamically and one of the issue that I came across is, I couldnt find an option to programmatically set the job to "PersistJobDataAfterExecution" and "DisallowConcurrentExecution" as both are annotation. Can any of you please suggest whats the equivalent while scheduling a job programmatically ( not declarative )

Since you are scheduling dynamically you should be passing a JobDetail to the Scheduler. You should be able to create your own JobDetail implementation or extends the base implementation then return whatever you want for the corresponding methods.

Related

Spring + Quartz: programmatic schedule of one-time, misfire proof jobs

I am working on an enterprise application that uses Quartz 2.2.1.
Trigger beans are configured in their XML, which included the relative cron expression.
Now, I have the need of programmatically creating triggers with custom fire times; these triggers also have to handle misfiring (I have to be sure that they get executed, even if the server is down at fire time). Is there a way to make quartz do the 'dirty' work without handling trigger persistency manually?
Thank you.
Easier than I thought, solution lies within the SimpleTrigger class.
// Update trigger infos
SimpleTrigger trigger = (SimpleTrigger)builder
.startAt( whenever you want it to start )
.withSchedule(simpleSchedule()
.withIntervalInMinutes( or any interval ).repeatForever() )
.endAt( whenever you want it to end)
.build()
This creates a quartz trigger living between start and end, and executing following the specified interval.
Misfire strategy can be specified as well.

Is Spring's built in Scheduler persistent.?

I have run into a case where I have to use a persistent Scheduler, since I have a web application that can crash or close due to some problems and might lose it job details if this happens . I have tried the following:
Use Quartz scheduler:
I used RAMJobStore first, but since it isn't persistent, it wasn't of much help. Can't setup JDBCJobStore because, this will require huge code changes to my existing code base.
In light of such a scenario,
I have the following queries:
If I use Spring's built in #Schedule annotation will my jobs be persistent..? I don't mind if the jobs get scheduled after the application starts. All I want is the jobs to not lose their details and triggers.?
If not, are there any other alternatives that can be followed , keeping in mind that I need to schedule multiple jobs with my scheduler.?
If yes, how can I achieve this.? My triggers are different each job. For e.g I might have a job that is scheduled at 9AM and another at 8.30AM and so on.
If not a scheduler, then can I have a mechanism to handle this.?
One thing, I found is that the documentation for Quartz isn't very descriptive. I mean it's fine for a top level config, but configuring it on your an application is a pain. This is just a side note. Nothing to do with the question.
Appreciate the help. :)
No, Spring's #Schedule-annotation will typically only instruct Spring at what times a certain task should be scheduled to run within the current VM. As far as I know there is not a context for the execution either. The schedule is static.
I had a similar requirement and created db-scheduler (https://github.com/kagkarlsson/db-scheduler), a simple, persistent and cluster-friendly scheduler. It stores the next execution-time in the database, and triggers execution once it is reached.
A very simple example for a RecurringTask without context could look like this:
final RecurringTask myDailyTask = ComposableTask.recurringTask("my-daily-task", Schedules.daily(LocalTime.of(8, 0)),
() -> System.out.println("Executed!"));
final Scheduler scheduler = Scheduler
.create(dataSource)
.startTasks(myDailyTask)
.threads(5)
.build();
scheduler.start();
It will execute the task named my-daily-task at 08:00 every day. It will be scheduled in the database when the scheduler is first started, unless it already exists in the database.
If you want to schedule an ad-hoc task some time in the future with context, you can use the OneTimeTask:
final OneTimeTask oneTimeTask = ComposableTask.onetimeTask("my-onetime-task",
(taskInstance, context) -> System.out.println("One-time task with identifier "+taskInstance.getId()+" executed!"));
scheduler.scheduleForExecution(LocalDateTime.now().plusDays(1), oneTimeTask.instance("1001"));
See the example above. Any number of tasks can be scheduled, as long as task-name and instanceIdentifier is unique.
#Schedule has nothing to do with the actual executor. The default java executors aren't persistent (maybe there are some app-server specific ones that are), if you want persistence you have to use Quartz for job execution.

How to do “sequential” Job Scheduling (Quartz?)

I'm making use of Quartz Scheduling and there are 2 jobs. First Job is performing the tasks for around 2 minutes and the Second one is to be setup for Cleaning Operations of Temporary Files. So, I need to setup the Schedule to work in a way that after the first job is executed/finished performing tasks I need to do the cleaning operations with the help of Second Job.
Considering the Example 9 - Job Listeners under Quartz 2.1.x which states that we can define a method named jobWasExecuted( _, _ ); in the Job Listener and it executes when the 1st job is executed/or comes in running state.
Are we able to setup the schedule which can listen for the first job finishing then executes second? or,
Are we able to define the join() method like in Java Multithreading which can execute on the completion of first job?
There currently is no "direct" or "free" way to chain triggers with
Quartz. However there are several ways you can accomplish it without
much effort. Below is an outline of a couple approaches:
One way is to use a listener (i.e. a TriggerListener, JobListener or
SchedulerListener) that can notice the completion of a job/trigger and
then immediately schedule a new trigger to fire. This approach can get
a bit involved, since you'll have to inform the listener which job
follows which - and you may need to worry about persistence of this
information.
Another way is to build a Job that contains within its JobDataMap the name of the next job to fire, and as the job completes (the last step in its Execute() method) have the job schedule the next job. Several people are doing this and have had good luck. Most have made a base (abstract) class that is a Job that knows how to get the job name and group out of the JobDataMap using special keys (constants) and contains code to schedule the identified job. Then
they simply make extensions of this class that included the additional
work the job should do.
Ref: http://www.quartz-scheduler.net/documentation/faq.html#how-do-i-chain-job-execution?-or,-how-do-i-create-a-workflow?
I know this is an old question, but nevertheless there are 2 more options available to chain the execution of your jobs which people can find useful:
1) Use the JobChainingJobListener that is included in the standard Quartz distribution since very early releases. This listener allows you to programmatically define simple job chains using its addJobChainLink method.
2) Use a commercial solution such as QuartzDesk that I am the principal developer of. QuartzDesk contains a robust job chaining engine that allows you to externalize the definition of your job chains from the application code and enables you to update your job chains at runtime through a GUI without modifying, redeploying and restarting your application. A job chain can be associated with a particular job, trigger or it can be a global job chain that is executed whenever any of your jobs execute (useful for global job execution failure handlers etc.).
From http://www.quartz-scheduler.net/documentation/faq.html#how-do-i-chain-job-execution?-or,-how-do-i-create-a-workflow
How do I keep a Job from firing concurrently?
Quartz.NET 2.x
Implement IJob and also decorate your job class with
[DisallowConcurrentExecution] attribute. Read the API documentation
for DisallowConcurrentExecutionAttribute for more information.
The annotation is available in the Java implementation.

Adding a trigger in Quartz scheduler for future use

Quartz API provide a way in which i can create a Job and add it to scheduler for future use by doing something like
SchdularFactory.getSchedulerInstance().addJob(jobDetail, false);
This provides me the flexibility to create jobs store them with the scheduler and use them in later stage.
i am wondering is there any way i can create triggers and add them to scheduler to be used in future.
Not sure if this is valid requirement but if its not possible than all i have to do is to associate the Trigger with any given/existing Job
In Quartz there is a one-to-many relationship between jobs and triggers, which is understandable: one job can be run by several different triggers but one trigger can only run a single job. If you need to run several jobs, create one composite job that runs these jobs manually.
Back to your question. Creating a job without associated triggers is a valid use-case: you have a piece of logic and later you will attach one or more triggers to execute it at different points in time.
The opposite situation is weird - you want to create a trigger that will run something at a given time, but you don't know yet what. I can't imagine use-case for that.
Note that you can create a trigger for future use (with next fire time far in the future), but it must have a job attached.
Finally, check out How-To: Storing a Job for Later Use in the official documentation.

How to avoid firing same job by multiple threads in Quartz Schedular?

I have configured my job for every one minute. But some times same job get triggered by mutiple threads in milli seconds difference. I am using quartz1.6.
Can anyone help on this?? Also what is the usage of threadPool option in quartz.property file.
If you are using Java Spring, you need to set the concurrent property of the Job Detail bean to be false.
Have you tried:
org.quartz.jobStore.isClustered: true
Alternatively, you make your job into a Stateful job (and set isClustered to true), and that shoujld solve your problem.
(Oops, StatefulJob is deprecated; use DisallowConcurrentExecution.)

Categories

Resources