| | + title | Ref. /chapter[1]/title[1] |
| Original | Traduction | Scheduling jobs using Quartz or Timer |
| sect1
| | + title | Ref. /chapter[1]/sect1[1]/title[1] |
| Original | Traduction | Introduction |
|
| + para | Ref. /chapter[1]/sect1[1]/para[1] |
| Original | Traduction |
Spring features integration classes for scheduling support. Currently, Spring
supports the Timer, built in the JDK since 1.3 and the Quartz Scheduler
(). Both schedulers are set up
using a FactoryBean with optional references to Timers or Triggers, respectively.
Furthermore, a convenience class for both the Quartz Scheduler and the Timer is
available that allows you to invoke a method an a target object that you can
specify yourself (analogous to normal MethodInvokingFactoryBeans).
|
|
| | sect1
| | + title | Ref. /chapter[1]/sect1[2]/title[1] |
| Original | Traduction | Using the OpenSymphony Quartz Scheduler |
|
| + para | Ref. /chapter[1]/sect1[2]/para[1] |
| Original | Traduction |
Quartz uses Triggers, Jobs and
JobDetail ro realize scheduling of all kinds of jobs.
For the basic concepts behind Quartz, have a look at
. For convenience purposes,
Spring offers a couple of classes that simplify usage of Quartz within
Spring-based applications.
|
| sect2
| | + title | Ref. /chapter[1]/sect1[2]/sect2[1]/title[1] |
| Original | Traduction | Using the JobDetailBean |
|
JobDetail objects contain all information needed to
run a job. Spring provides a so-called JobDetailBean
that makes the JobDetail more of an actual JavaBean with sensible defaults.
Let's have a look at an example:
| + programlisting | Ref. /chapter[1]/sect1[2]/sect2[1]/programlisting[1] |
| Original | Traduction |
<bean name="exampleJob" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass">
<value>example.ExampleJob</value>
</property>
<property name="jobDataAsMap">
<map>
<entry key="timeout"><value>5</value></entry>
</map>
</property>
</bean>
|
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[1]/para[2] |
| Original | Traduction |
The job detail bean has all information it needs to run the job (ExampleJob).
The timeout is specified as 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:
|
|
| + programlisting | Ref. /chapter[1]/sect1[2]/sect2[1]/programlisting[2] |
| Original | Traduction |
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
}
}
|
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[1]/para[3] |
| Original | Traduction |
All additional settings from the job detail bean are by the way available to you as well.
|
|
Note: Using the name and group properties,
you can modify in which group the job runs and using what name. By default the
name of the job equals the bean name of the job detail bean (in the example above this is
exampleJob).
| | sect2
| | + title | Ref. /chapter[1]/sect1[2]/sect2[2]/title[1] |
| Original | Traduction | Using the MethodInvokingJobDetailFactoryBean |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[2]/para[1] |
| Original | Traduction |
Often times, you just need to invoke a method on a specific object. Using the
MethodInvokingJobDetailFactoryBean you can do exactly this:
|
|
| + programlisting | Ref. /chapter[1]/sect1[2]/sect2[2]/programlisting[1] |
| Original | Traduction |
<bean id="methodInvokingJobDetail"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject"><ref bean="exampleBusinessObject"/></property>
<property name="targetMethod"><value>doIt</value></property>
</bean>
|
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[2]/para[2] |
| Original | Traduction |
The above example will result in the doIt being called on the exampleBusinessObject
(see below):
|
|
| + programlisting | Ref. /chapter[1]/sect1[2]/sect2[2]/programlisting[2] |
| Original | Traduction |
public class BusinessObject {
// properties and collaborators
public void doIt() {
// do the actual work
}
}
|
|
| + programlisting | Ref. /chapter[1]/sect1[2]/sect2[2]/programlisting[3] |
| Original | Traduction |
<bean id="exampleBusinessObject" class="examples.ExampleBusinessObject"/>
|
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[2]/para[3] |
| Original | Traduction |
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.
|
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[2]/para[4] |
| Original | Traduction |
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 objects
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.
|
|
| + programlisting | Ref. /chapter[1]/sect1[2]/sect2[2]/programlisting[4] |
| Original | Traduction |
<bean id="methodInvokingJobDetail"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject"><ref bean="exampleBusinessObject"/></property>
<property name="targetMethod"><value>doIt</value></property>
<property name="concurrent"><value>false</value></property>
</bean>
|
|
Note: By default, jobs will run in a concurrent fashion.
| | sect2
| | + title | Ref. /chapter[1]/sect1[2]/sect2[3]/title[1] |
| Original | Traduction | Wiring up jobs using triggers and the SchedulerFactoryBean |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[3]/para[1] |
| Original | Traduction |
We've created job details, jobs and we've 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, the CronTriggerBean
and the SimpleTriggerBean.
|
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[3]/para[2] |
| Original | Traduction |
Triggers need to be scheduled. Spring offers a SchedulerFactoryBean exposing properties
to set the triggers. The SchedulerFactoryBean schedules the actual triggers.
|
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[3]/para[3] |
| Original | Traduction |
A couple of examples:
|
|
| + programlisting | Ref. /chapter[1]/sect1[2]/sect2[3]/programlisting[1] |
| Original | Traduction |
<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="jobDetail">
<!-- see the example of method invoking job above -->
<ref bean="methodInvokingJobDetail"/>
</property>
<property name="startDelay">
<!-- 10 seconds -->
<value>10000</value>
</property>
<property name="repeatInterval">
<!-- repeat every 50 seconds -->
<value>50000</value>
</property>
</bean>
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail">
<ref bean="exampleJob"/>
</property>
<property name="cronExpression">
<!-- run every morning at 6 am -->
<value>0 6 * * 1</value>
</property>
</bean>
|
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[3]/para[4] |
| Original | Traduction |
Ok, 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. To finalize everything we need to set up the
SchedulerFactoryBean:
|
|
| + programlisting | Ref. /chapter[1]/sect1[2]/sect2[3]/programlisting[2] |
| Original | Traduction |
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref local="cronTrigger"/>
<ref local="simpleTrigger"/>
</list>
</property>
</bean>
|
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[3]/para[5] |
| Original | Traduction |
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, etcetera. Have a look
at the JavaDoc ()
for more information.
|
|
| |
| | sect1
| | + title | Ref. /chapter[1]/sect1[3]/title[1] |
| Original | Traduction | Using JDK Timer support |
|
| + para | Ref. /chapter[1]/sect1[3]/para[1] |
| Original | Traduction |
The other way to schedule jobs is using the JDK Timer objects. More information
about Timers themselves can be found at
.
The concepts discussed above also apply to the Timer support. You can create
custom timers or use the timer that invokes methods. Wiring timers has to be done
using the TimerFactoryBean.
|
| sect2
| | + title | Ref. /chapter[1]/sect1[3]/sect2[1]/title[1] |
| Original | Traduction | Creating custom timers |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[1]/para[1] |
| Original | Traduction |
Using the TimerTask you can create customer timer tasks, similar to Quartz jobs:
|
|
| + programlisting | Ref. /chapter[1]/sect1[3]/sect2[1]/programlisting[1] |
| Original | Traduction |
public class CheckEmailAddresses extends TimerTask {
private List emailAddresses;
public void setEmailAddresses(List emailAddresses) {
this.emailAddresses = emailAddresses;
}
public void run() {
// iterate over all email addresses and archive them
}
}
|
|
| + programlisting | Ref. /chapter[1]/sect1[3]/sect2[1]/programlisting[2] |
| Original | Traduction |
<bean id="checkEmail" class="examples.CheckEmailAddress">
<property name="emailAddresses">
<list>
<value>test@springframework.org</value>
<value>foo@bar.com</value>
<value>john@doe.net</value>
</list>
</property>
</bean>
<bean id="scheduledTask" class="org.springframework.scheduling.timer.ScheduledTimerTask">
<!-- wait 10 seconds before starting repeated execution -->
<property name="delay">
<value>10000</value>
</property>
<!-- run every 50 seconds -->
<property name="period">
<value>50000</value>
</property>
<property name="timerTask">
<ref local="checkEmail"/>
</property>
</bean>
|
|
| | sect2
| | + title | Ref. /chapter[1]/sect1[3]/sect2[2]/title[1] |
| Original | Traduction | Using the MethodInvokingTimerTaskFactoryBean |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/para[1] |
| Original | Traduction |
Similar to the Quartz support, the Timer support also features a component that
allows you to periodically invoke a method:
|
|
| + programlisting | Ref. /chapter[1]/sect1[3]/sect2[2]/programlisting[1] |
| Original | Traduction |
<bean id="methodInvokingTask"
class="org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean">
<property name="targetObject"><ref bean="exampleBusinessObject"/></property>
<property name="targetMethod"><value>doIt</value></property>
</bean>
|
| doIt | + programlisting | Ref. /chapter[1]/sect1[3]/sect2[2]/programlisting[2] |
| Original | Traduction |
public class BusinessObject {
// properties and collaborators
public void doIt() {
// do the actual work
}
}
|
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/para[2] |
| Original | Traduction |
Changing the reference of the above example in which the ScheduledTimerTask is mentioned to the
methodInvokingTask will result in this task being executed.
|
|
| | sect2
| | + title | Ref. /chapter[1]/sect1[3]/sect2[3]/title[1] |
| Original | Traduction | Wrapping up: setting up the tasks using the TimerFactoryBean |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[3]/para[1] |
| Original | Traduction |
The TimerFactoryBean is similar to the Quartz SchedulerFactoryBean in that it serves the same
purpose: setting up the actual scheduling. The TimerFactoryBean sets up an actual Timer and
schedules the tasks it has references to. You can specify whether or not daemon threads should
be used.
|
|
| + programlisting | Ref. /chapter[1]/sect1[3]/sect2[3]/programlisting[1] |
| Original | Traduction |
<bean id="timerFactory" class="org.springframework.scheduling.timer.TimerFactoryBean">
<property name="scheduledTimerTasks">
<list>
<!-- see the example above -->
<ref local="scheduledTask"/>
</list>
</property>
</bean>
|
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[3]/para[2] |
| Original | Traduction |
That's all!
|
|
| |
| |
|