JobDetail JobDataMap vs Trigger JobDataMap for one job with multiple inputs - quartz-scheduler

I have one job class that will get executed with different user inputs. I realize that I can specify the JobDataMap on both JobDetail and Trigger. So, I have two options in my case, if I understand it right:
(1) JobDataMap on JobDetail - when a user specifies new inputs and a schedule, create a new JobDetail with those inputs and create a new trigger. Then add the newly created jobDetail and trigger to the scheduler.
(2) JobDataMap on Trigger - when a user specifies new inputs and a schedule, create a new trigger with those inputs and add the trigger to the scheduler for the already added jobDetail.
Is there is a reason to prefer one option over the other?
Thanks.

From my personal experience, I have to say that we use the first approach (specify job params on JobDetail).
The main reason behing this decision is that is seems more simple and clean to understand and maintain.
When a user schedules a job with specific parameters, we create a JobDetail with JobDataMap populated accordingly.
The Trigger of this scheduled job may be fired many times, and we have to make sure that the parameters won't change and stay the same for all job executions.
If a user wants to schedule a job of the same type with different parameters, a new JobDetail is being created and added to the scheduler.
This way, we assume JobDetail to be our main "Job Definition" containing all the information needed to run the job (custom parameters, arguments etc) and we are leaving Trigger objects to deal with the execution times.
Just my two cents.

Related

QuartzScheduler Schedule Job instances instead of JobDetail

I want to schedule Job instances instead of JobDetail.
So something like schedule(Job job, Trigger trigger) ?
Does exists possibility do it?
No, you can't schedule a Job. You have to use JobDetail.
Job is just an interface with an execute() method. It doesn't offer a way to obtain the job's name, or the job's key, or the job's data map, or whether it's a durable job, or any of the required info that Quartz needs to properly manage the job.
That's why the class JobDetail exists, so you can have all that info in a different object that you can instantiate only when you need to, instead of having to implement all those methods in your SomeJob implements Job class. You can even create multiple JobDetail objects for the same Job class with different properties, as long as you give them different IDs.
There's no reason not to use it, IMHO.

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

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.

Creating a custom scheduler using spring quartz

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

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.