Creating a custom scheduler using spring quartz - quartz-scheduler

I have a requirement to create a custom scheduler. I would like all the parameters defining the frequency that my jobs will run to be stored in db tables. This would allow my customers to change the frequency etc via a nice little webapp (webapp is a different application to my main one).
I know using quartz you can define all your job triggers programatically but is that just at start time? How would it work if my customer logs on a changes the schedule in the webapp. Am I able to re-define a job trigger in the original app by checking for changes periodially?
Does anyone know of any nice examples of this?
regards

You have bunch of methods in Scheduler interface. JavaDoc here.
Replace already scheduled job with :
Add a new job with replace=true in addJob method
OR
Deleting an existing job ( method: deletejob )
And then adding a new job with modified details ( addjob)
Replace already scheduled triggers with
rescheduleJob ( If jobdetail associated with previous trigger is same for new trigger too )
OR
unscheduleJob followed by scheduleJob

If used with spring you can use spring.quartz.overwrite-existing-jobs=true

Related

deploying Batch with CloudFormation

I've been able to create a Compute Environment, a Job Queue and about a dozen Job Definitions using CloudFormation. Great!
Unless I'm missing something, there doesn't seem to be an element to actually submit my Job Definitions using CloudFormation. :(
At first, I thought I had it figured out because you can create CloudWatch Events that trigger a Job Submission. However, I notice that the Event Rule in CloudFormation does not have support for Batch like the CLI/SDK does. Lame!
Anyone else deploying Batch with CloudFormation? How are you submitting jobs? I guess I can create a Custom Resource, but that seems harder than it should be.
Does https://docs.aws.amazon.com/batch/latest/userguide/batch-cwe-target.html solve your problem?
AWS Batch jobs are available as CloudWatch Events targets. Using simple rules that you can quickly set up, you can match events and submit AWS Batch jobs in response to them.
When you create a new rule, add the batch job as a target.
The easiest way would be to create a Lambda function. You can create it via CF and capture your requirement in the function code.
Or like you mentioned, you can create a custom resource.

Quartz capabilities

I am trying to create a Quartz scheduler using Java which will be able to call an API and pass in data.
I am totally new to Quartz but now I understand the Job concept and how to create one. I understand the trigger concept and how to trigger one
and I understand how the scheduler works.
What I am having difficult with is how can I pass in the information which is required to be passed to the API. I have an example of an API being called and the data is entered into the DB but the information has been hard coded into the class be passed into the JobDetails.
Ie. the user passes a message to the system which needs to be sent to the user in 12 hours and not before, so what i was planning was create a Job and a trigger in to set the execute time to 12 hours. How to do i pass the message into the scheduler? Where should this message be stored? Is what I am trying to do possible? Have i misunderstood what Quartz is capable of doing?
Thank you for your time. Any assistance would be greatly appreciated.
Take a look at JobDataMap. If you are creating a new job for each user action you can store the message in there which will be available during the execution.
JobDataMap Holds state information for Job instances.
JobDataMap instances are stored once when the Job is added to a scheduler. They are also re-persisted after every execution of jobs annotated with #PersistJobDataAfterExecution.
JobDataMap instances can also be stored with a Trigger. This can be useful in the case where you have a Job that is stored in the scheduler for regular/repeated use by multiple Triggers, yet with each independent triggering, you want to supply the Job with different data inputs.
The JobExecutionContext passed to a Job at execution time also contains a convenience JobDataMap that is the result of merging the contents of the trigger's JobDataMap (if any) over the Job's JobDataMap (if any).
In case you have a single job but for each user action you are creating a new trigger, you can follow the solution given here.
Third option will be, for each user action, persist the message and time to send email to the database. Have a job that runs periodically and scans through database for eligible records for which email has to be sent

Spring integration dynamic trigger with cron expression

I saw the sample dynamic trigger in github and it is using fixed rate/delay but is it possible to implement dynamic trigger with cron expression where once job is completed with custom exit code we want the cron expression in such a way that it no longer poll for that day or change cron expressin to start polling from diff time onwards.
Unfortunately org.springframework.scheduling.support.CronTrigger uses final field, so we can't change its state at runtime. Therefore any ideas to seek the way how to change cron-expression value is a waste of time.
From other let's take a look at this as just a time producer solution to notify the scheduler when to start a provided task.
In other words here is a Trigger contract source code:
public interface Trigger {
Date nextExecutionTime(TriggerContext triggerContext);
}
So, what our solution must supply is just only returning the specific Date for each nextExecutionTime invocation.
Only what you need to do here is that dynamic trigger implementation which fits to your requirements.
Right, it might be a bit difficult to reach cron-similar behavior, but there is no choice for you right now...
Although you can stop() you adapter after the task, inject a new CronTrigger to it and start() it again.
You can write a custom trigger that simply wraps a CronTrigger and you can replace the delegate CronTrigger at will.
However, a limitation of the Trigger mechanism is you can't change an existing schedule.
If you are running your job on the poller thread, then you can change the trigger before the poller thread returns (and calls the trigger to find the next execution time).
Spring Integration 4.2 (currently at milestone 2) has conditional pollers which will make things like this a little easier.

quartz-scheduler depend jobs

I'm working on a project with Quartz and has been a problem with the dependencies with jobs.
we have a setup where A and B aren't dependent on eachother, though C is:
A and B can run at the same time, but C can only run when both A and B are complete.
Is there a way to set this kind of scenario up in Quartz, so that C will only trigger when A and B finish?
Not directly AFAIK, but it should be not too hard to use a TriggerListener to implement such a functionality (a TriggerListener is run both a start and end of jobs, and you can set them up for individual triggers or trigger groups).
EDIT: there is even a specific FAQ Topic about this problem:
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. See the listener
org.quartz.listeners.JobChainingJobListener which ships with Quartz -
as it already has some of this functionality.
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 pre-defined keys (constants) and
contains code to schedule the identified job. This abstract Job's
implementation of execute() delegates to an abstract template method
such as "doWork()" (where the extending Job class's real work goes)
and then it contains the code for scheduling the follow-up job. Then
they simply make extensions of this class that included the work the
job should do. The usage of 'durable' jobs, or the overloaded
addJob(JobDetail, boolean, boolean) method (added in Quartz 2.2) helps
the application define all the jobs at once with their proper data,
without yet creating triggers to fire them (other than one trigger to
fire the first job in the chain).
In the future, Quartz will provide a much cleaner way to do this, but
until then, you'll have to use one of the above approaches, or think
of yet another that works better for you.

How to make a quartz job create another job to execute after it?

I am tying to implement the following algorithm with Quartz and not really sure if it can be done. This is my first attempt at using quartz.
User notification Job - This job computes a monthly report and emails to a user, it expects a user id and other parameters that are used to generate the customized user report
There are potentially 10,000+ of these reports that need to be generated
Monthly Job to figure who needs reports Fires
search the database to look for users that need to be sent a monthly report
for each user found create a jobDetail that will compute the monthly report and deliver it to report sender that takes care of sending the report
schedule each of the jobDetails from step 2 to execute right after this job finishes
What I have not been able to figure out.
How to make sure that monthly job executes in a single transaction so that all users that need a monthly report are identified and jobs are scheduled to notify them
How to schedule a job right away to execute right after the job that created them?
I am using Spring 3.2 an Quartz 2.1
Nice use case for quartz usage.
You can try sheduling a new job from within the job class. This can be possibly with by creating a new jobdetail and trigger from inside execute() method.