The Spring Framework features integration classes for scheduling
support. Currently, Spring supports the Quartz Scheduler (http://quartznet.sourceforge.net/). The scheduler is set up
using a IFactoryObject
with optional
references to Trigger
instances, respectively.
Furthermore, a convenience class for both the Quartz Scheduler is
available that allows you to invoke a method of an existing target
object.
Quartz uses Trigger
,
Job
and JobDetail
objects to
realize scheduling of all kinds of jobs. For the basic concepts behind
Quartz, have a look at http://quartznet.sourceforge.net/. For convenience
purposes, Spring offers a couple of classes that simplify the usage of
Quartz within Spring-based applications.
JobDetail
objects contain all information
needed to run a job. The Spring Framework provides a
JobDetailObject
that makes the
JobDetail
easier to configure and with sensible
defaults. Let's have a look at an example:
<object name="ExampleJob" type="Spring.Scheduling.Quartz.JobDetailObject, Spring.Scheduling.Quartz"> <property name="JobType" value="Example.Quartz.ExampleJob, Example.Quartz" /> <property name="JobDataAsMap"> <dictionary> <entry key="Timeout" value="5" /> </dictionary> </property> </object>
The job detail object has all information it needs to run the job
(ExampleJob
). The timeout is specified in the job
data dictionary. The job data dictonary is available through the
JobExecutionContext
(passed to you at execution
time), but the JobDetailObject
also maps the
properties from the job data map to properties of the actual job. So in
this case, if the ExampleJob
contains a property
named Timeout
, the
JobDetailObject
will automatically apply
it:
namespace Example.Quartz; public class ExampleJob extends QuartzJobObject { private int timeout; /// <summary> /// Setter called after the ExampleJob is instantiated /// with the value from the JobDetailObject (5) /// </summary> public int Timeout { set { timeout = value; }; } protected override void ExecuteInternal(JobExecutionContext context) { // do the actual work } }
All additional settings from the job detail object are of course available to you as well.
Note: Using the name
and
group
properties, you can modify the name and the
group of the job, respectively. By default, the name of the job matches
the object name of the job detail object (in the example above, this is
ExampleJob
).
Often you just need to invoke a method on a specific object. Using
the MethodInvokingJobDetailFactoryObject
you can
do exactly this:
<object id="JobDetail" type="Spring.Scheduling.Quartz.MethodInvokingJobDetailFactoryObject, Spring.Scheduling.Quartz"> <property name="TargetObject" ref="ExampleBusinessObject" /> <property name="TargetMethod" value="DoIt" /> </object>
The above example will result in the doIt
method being called on the exampleBusinessObject
method (see below):
public class ExampleBusinessObject { // properties and collaborators public void DoIt() { // do the actual work } }
<object id="ExampleBusinessObject" type="Examples.BusinessObjects.ExampleBusinessObject, Examples.BusinessObjects"/>
Using the
MethodInvokingJobDetailFactoryObject
, you don't
need to create one-line jobs that just invoke a method, and you only
need to create the actual business object and wire up the detail
object.
By default, Quartz Jobs are stateless, resulting in the
possibility of jobs interfering with each other. If you specify two
triggers for the same JobDetail
, it might be
possible that before the first job has finished, the second one will
start. If JobDetail
classes implement the
Stateful
interface, this won't happen.
The second job will not start before the first one has finished. To make
jobs resulting from the
MethodInvokingJobDetailFactoryObject
non-concurrent, set the concurrent
flag to
false
.
<object id="JobDetail" type="Spring.Scheduling.Quartz.MethodInvokingJobDetailFactoryObject, Spring.Scheduling.Quartz"> <property name="TargetObject" ref="ExampleBusinessObject" /> <property name="TargetMethod" value="DoIt" /> <property name="Concurrent" value="false" /> </object>
![]() | Note |
---|---|
By default, jobs will run in a concurrent fashion. Also note that when using MethodInvokingJobDetailFactoryObject you can't use database persistence for Jobs. See the class documentation for additional details. |
We've created job details and jobs. We've also reviewed the
convenience class that allows to you invoke a method on a specific
object. Of course, we still need to schedule the jobs themselves. This
is done using triggers and a
SchedulerFactoryObject
. Several triggers are
available within Quartz. Spring offers two subclassed triggers with
convenient defaults: CronTriggerObject
and
SimpleTriggerObject
Triggers need to be scheduled. Spring offers a
SchedulerFactoryObject
that exposes triggers to
be set as properties. SchedulerFactoryObject
schedules the actual jobs with those triggers.
Find below a couple of examples:
<object id="SimpleTrigger" type="Spring.Scheduling.Quartz.SimpleTriggerObject, Spring.Scheduling.Quartz"> <!-- see the example of method invoking job above --> <property name="JobDetail" ref="ExampleJob" /> <!-- 10 seconds --> <property name="StartDelay" value="10s" /> <!-- repeat every 50 seconds --> <property name="RepeatInterval" value="50s" /> </object> <object id="CronTrigger" type="Spring.Scheduling.Quartz.CronTriggerObject, Spring.Scheduling.Quartz"> <property name="JobDetail" ref="ExampleJob" /> <!-- run every morning at 6 AM --> <property name="CronExpressionString" value="0 0 6 * * ?" /> </object>
Now we've set up two triggers, one running every 50 seconds with a
starting delay of 10 seconds and one every morning at 6 AM. To finalize
everything, we need to set up the
SchedulerFactoryObject
:
<object id="quartzSchedulerFactory" type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz"> <property name="triggers"> <list> <ref object="CronTrigger" /> <ref object="SimpleTrigger" /> </list> </property> </object>
More properties are available for the
SchedulerFactoryObjecct
for you to set, such as
the calendars used by the job details, properties to customize Quartz
with, etc. Have a look at the SchedulerFactoryObject
SDK docs for more information.