QuartzScheduler Schedule Job instances instead of JobDetail - quartz-scheduler

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.

Related

JobDetail JobDataMap vs Trigger JobDataMap for one job with multiple inputs

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.

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

Using Job instances instead of Job classes in Quartz

I would like to know if it is possible to schedule a Job-Instance instead of a Job class.
I'm creating my own Job Instances and don't have the possibility to use the Job.class directly.
So something like schedule(Job job, Trigger trigger) would be great?

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 can I use a property on my Job instead of JobDataMap dictionary in Quartz.NET?

I am working on a Windows service which needs to schedule tasks whenever one of it's web services is called. This could happen hundreds of times per second in a worst case scenario. The task needs to wait a period of time, typically a minute or two, then call a method passing a parameter.
We tried to build our own scheduler class to do this:
public void ScheduleTask<T>(TimeSpan delay, Action<T> task, T arg)
{
Thread.Sleep(delay);
threadPool.ExecuteAsync(task, arg);
}
But we figured this wouldn't be appropriate because we could theoretically end up with hundreds of Thread Pool threads all waiting. I am under the impression that there is a finite number of Thread Pool threads available and that this could potentially lock up the system.
I then turned to Quartz.NET and read on their features page that:
Job class instances can be instantiated by Quartz.NET, or by your application's framework.
and on page 3 of their tutorial that the Scheduler creates instances of your Job class (not you) and as such:
it does not make sense to have data-members defined on the job class as their values would be 'cleared' every time the job executes.
Feel free to yell at me, but how do I get a reference to my Job class instance before it executes so I can set a property on it?
The property is doing the job of a
parameter so i have no interest in it
after the Job has executed.
I also want to minimise the number of
objects it takes to acheive this to
keep my code neat and simple.
Finally, I seriously dislike using
Dictionaries so would prefer to avoid the JobDataMap object.
I don't understand exactly what your use case is and why you would need to set a property on the job, but to answer your question: to get access to your job before it executes you need to create a job listener (implement IJobListener). The job listener gets called just before the job gets executed, so you could set a property at that point.
Some links:
The documentation on job listeners
I wrote a blog post detailing the creation of listeners, here.