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://www.opensymphony.com/quartz. 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 JobDetailBean
that makes the JobDetail
more of an actual JavaBean
with sensible defaults. Let's have a look at an example:
<bean name="exampleJob" class="org.springframework.scheduling.quartz.JobDetailBean"> <property name="jobClass" value="example.ExampleJob" /> <property name="jobDataAsMap"> <map> <entry key="timeout" value="5" /> </map> </property> </bean>
The job detail bean has all information it needs to run the job (ExampleJob
).
The timeout is specified in the job data map. The job data map is
available through the JobExecutionContext
(passed to you at execution time), but the JobDetailBean
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 JobDetailBean
will
automatically apply it:
package example; public class ExampleJob extends QuartzJobBean { private int timeout; /** * Setter called after the ExampleJob is instantiated * with the value from the JobDetailBean (5) */ public void setTimeout(int timeout) { this.timeout = timeout; } protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException { // do the actual work } }
All additional settings from the job detail bean 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 bean name of the job detail bean (in the example above, this is
exampleJob
).
Often you just need to invoke a method on a specific object. Using the
MethodInvokingJobDetailFactoryBean
you can do exactly this:
<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="exampleBusinessObject" /> <property name="targetMethod" value="doIt" /> </bean>
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 } }
<bean id="exampleBusinessObject" class="examples.ExampleBusinessObject"/>
Using the MethodInvokingJobDetailFactoryBean
, 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
MethodInvokingJobDetailFactoryBean
non-concurrent, set the
concurrent
flag to false
.
<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="exampleBusinessObject" /> <property name="targetMethod" value="doIt" /> <property name="concurrent" value="false" /> </bean>
Note | |
---|---|
By default, jobs will run in a concurrent fashion. |
We've created job details and jobs. We've also reviewed the convenience bean
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
SchedulerFactoryBean
. Several triggers are available
within Quartz. Spring offers two subclassed triggers with convenient defaults:
CronTriggerBean
and SimpleTriggerBean
.
Triggers need to be scheduled. Spring offers a SchedulerFactoryBean
that exposes triggers to be set as properties. SchedulerFactoryBean
schedules the actual jobs with those triggers.
Find below a couple of examples:
<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean"> <!-- see the example of method invoking job above --> <property name="jobDetail" ref="jobDetail" /> <!-- 10 seconds --> <property name="startDelay" value="10000" /> <!-- repeat every 50 seconds --> <property name="repeatInterval" value="50000" /> </bean> <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail" ref="exampleJob" /> <!-- run every morning at 6 AM --> <property name="cronExpression" value="0 0 6 * * ?" /> </bean>
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
SchedulerFactoryBean
:
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="cronTrigger" /> <ref bean="simpleTrigger" /> </list> </property> </bean>
More properties are available for the SchedulerFactoryBean
for you
to set, such as the calendars used by the job details, properties to customize Quartz with,
etc. Have a look at the
SchedulerFactoryBean Javadoc
for more information.