248 lines
12 KiB
XML
248 lines
12 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!--
|
|
/*
|
|
* Copyright 2002-2008 the original author or authors.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
-->
|
|
<chapter xml:id="quartz-quickstart" xmlns="http://docbook.org/ns/docbook" version="5">
|
|
<title>Quartz QuickStart</title>
|
|
|
|
<section>
|
|
<title>Introduction</title>
|
|
|
|
<para>In many applications the need arises to perform a certain action at
|
|
a given time without any user interaction, usually to perform some
|
|
administrative tasks. These tasks need to be scheduled, say to perform a
|
|
job in the early hours of the morning before the start of business. This
|
|
functionality is provided by using job scheduling software. Quartz.NET is
|
|
an excellent open source job scheduler that can be used for these
|
|
purposes. It provides a wealth of features, such as persistent jobs and
|
|
clustering. To find out more about Quartz.NET visit their <ulink
|
|
url="http://quartznet.sourceforge.net/">web site</ulink>. Spring
|
|
integration allows you to use Spring to configure Quartz jobs, triggers,
|
|
and schedulers and also provides integration with Spring's transaction
|
|
management features.</para>
|
|
|
|
<para>The full details of Quartz are outside the scope of this quickstart
|
|
but here is 'quick tour for the impatient' of the main classes and
|
|
interfaces used in Quartz so you can get your sea legs. A Quartz
|
|
<literal>IJob</literal> interface represents the task you would like
|
|
to execute. You either directly implement Quartz's
|
|
<literal>IJob</literal> interface or a convenience base class. The
|
|
Quartz <literal>Trigger</literal> controls when a job is executed, for
|
|
example in the wee hours of the morning every weekday . This would be done
|
|
using Quartz's <literal>CronTrigger</literal> implementation.
|
|
Instances of your job are created every time the trigger fires. As such,
|
|
in order to pass information between different job instances you stash
|
|
data away in a hashtable that gets passed to the each Job instance upon
|
|
its creation. Quartz's <literal>JobDetail</literal> class combines the
|
|
<literal>IJob</literal> and this hashtable of data. Instead of the
|
|
standard <literal>System.Collections.Hashtable</literal> the class
|
|
<literal>JobDataMap</literal> is used. Triggers are registered with a
|
|
Quartz <literal>IScheduler</literal> implementation that manages the
|
|
overall execution of the triggers and jobs. The
|
|
<literal>StdSchedulerFactory</literal> implementation is generally
|
|
used.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Application Overview</title>
|
|
|
|
<para>The sample application has two types of Jobs. One that inherits from
|
|
Spring's convenience base class <literal>QuartzJobObject</literal> and
|
|
another which does not inherit from any base class. The latter class is
|
|
adapted by Spring to be a Job. Two triggers, one for each of the jobs, are
|
|
created. These triggers are in turn registered with a scheduler. In each
|
|
case the job implementation will write information to the console when it
|
|
is executed.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Standard job scheduling</title>
|
|
|
|
<para>The Spring base class <literal>QuartzJobObject</literal>
|
|
implements <literal>IJob</literal> and allows for your object's
|
|
properties to be set via values that are stored inside Quartz's
|
|
<literal>JobDataMap</literal> that is passed along each time your job
|
|
is instantiated due a trigger firing. This class is shown below</para>
|
|
|
|
<programlisting language="csharp"> public class ExampleJob : QuartzJobObject
|
|
{
|
|
|
|
private string userName;
|
|
|
|
public string UserName
|
|
{
|
|
set { userName = value; }
|
|
}
|
|
|
|
protected override void ExecuteInternal(JobExecutionContext context)
|
|
{
|
|
Console.WriteLine("{0}: ExecuteInternal called, user name: {1}, next fire time {2}",
|
|
DateTime.Now, userName, context.NextFireTimeUtc.Value.ToLocalTime());
|
|
}
|
|
|
|
}</programlisting>
|
|
|
|
<para>The method <literal>ExecuteInternal</literal> is called when the
|
|
trigger fires and is where you would put your business logic. The
|
|
<literal>JobExecutionContext</literal> passed in lets you access
|
|
various pieces of information about the current job execution, such as the
|
|
JobDataMap or information on when the next time the trigger will fire. The
|
|
<literal>ExampleJob</literal> is configured by creating a
|
|
<literal>JobDetail</literal> object as shown below in the following
|
|
XML snippet taken from spring-objects.xml</para>
|
|
|
|
<programlisting language="myxml"> <object name="exampleJob" type="Spring.Scheduling.Quartz.JobDetailObject, Spring.Scheduling.Quartz">
|
|
<property name="JobType" value="Spring.Scheduling.Quartz.Example.ExampleJob, Spring.Scheduling.Quartz.Example" />
|
|
<!-- We can inject values through JobDataMap -->
|
|
<property name="JobDataAsMap">
|
|
<dictionary>
|
|
<entry key="UserName" value="Alexandre" />
|
|
</dictionary>
|
|
</property>
|
|
</object></programlisting>
|
|
|
|
<para>The dictionary property of the
|
|
<literal>JobDetailObject</literal>,
|
|
<literal>JobDataAsMap</literal>, is used to set the values of the
|
|
ExampleJob's properties. This will result in the ExampleJob being
|
|
instantiated with it's UserName property value set to 'Alexandre' the
|
|
first time the trigger fires.</para>
|
|
|
|
<para>We then will schedule this job to be executed on 20 second
|
|
increments of every minute as shown below using Spring's
|
|
<literal>CronTriggerObject</literal> which creates a Quartz
|
|
CronTrigger.</para>
|
|
|
|
<programlisting language="myxml"> <object id="cronTrigger" type="Spring.Scheduling.Quartz.CronTriggerObject, Spring.Scheduling.Quartz">
|
|
<property name="jobDetail" ref="exampleJob" />
|
|
<!-- run every 20 second of minute -->
|
|
<property name="cronExpressionString" value="0/20 * * * * ?" />
|
|
</object></programlisting>
|
|
|
|
<para>Lastly, we schedule this trigger with the scheduler as shown
|
|
below</para>
|
|
|
|
<programlisting language="myxml"> <object type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz">
|
|
<property name="triggers">
|
|
<list>
|
|
<ref object="cronTrigger" />
|
|
</list>
|
|
</property>
|
|
</object></programlisting>
|
|
|
|
<para>Running this configuration will produce the following output</para>
|
|
|
|
<programlisting>8/8/2008 1:29:40 PM: ExecuteInternal called, user name: Alexandre, next fire time 8/8/2008 1:30:00 PM
|
|
8/8/2008 1:30:00 PM: ExecuteInternal called, user name: Alexandre, next fire time 8/8/2008 1:30:20 PM
|
|
8/8/2008 1:30:20 PM: ExecuteInternal called, user name: Alexandre, next fire time 8/8/2008 1:30:40 PM</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Scheduling arbitrary methods as jobs</title>
|
|
|
|
<para>It is very convenient to schedule the execution of method as a job.
|
|
The AdminService class in the example demonstrates this functionality and
|
|
is listed below.</para>
|
|
|
|
<programlisting language="csharp"> public class AdminService
|
|
{
|
|
private string userName;
|
|
|
|
public string UserName
|
|
{
|
|
set { userName = value; }
|
|
}
|
|
|
|
public void DoAdminWork()
|
|
{
|
|
Console.WriteLine("{0}: DoAdminWork called, user name: {1}", DateTime.Now, userName);
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>Note that it does not inherit from any base class. To instruct
|
|
Spring to create a <literal>JobDetail</literal> object for this method
|
|
we use Spring's factory object class
|
|
<literal>MethodInvokingJobDetailFactoryObject</literal> as shown
|
|
below</para>
|
|
|
|
<programlisting language="myxml"> <object id="adminService" type="Spring.Scheduling.Quartz.Example.AdminService, Spring.Scheduling.Quartz.Example">
|
|
<!-- we inject straight to target object -->
|
|
<property name="UserName" value="admin-service" />
|
|
</object>
|
|
|
|
<object id="jobDetail" type="Spring.Scheduling.Quartz.MethodInvokingJobDetailFactoryObject, Spring.Scheduling.Quartz">
|
|
<!-- We don't actually need to implement IJob as we can use delegation -->
|
|
<property name="TargetObject" ref="adminService" />
|
|
<property name="TargetMethod" value="DoAdminWork" />
|
|
</object>
|
|
</programlisting>
|
|
|
|
<para>Note that <literal>AdminService</literal> object is configured
|
|
using Spring as you would do normally, without consideration for Quartz.
|
|
The trigger associated with the jobDetail object is listed below. Also
|
|
note that when using MethodInvokingJobDetailFactoryObject you can't use
|
|
database persistence for Jobs. See the class documentation for additional
|
|
details.</para>
|
|
|
|
<programlisting language="myxml"> <object id="simpleTrigger" type="Spring.Scheduling.Quartz.SimpleTriggerObject, Spring.Scheduling.Quartz">
|
|
<!-- see the example of method invoking job above -->
|
|
<property name="jobDetail" ref="jobDetail" />
|
|
<!-- 5 seconds -->
|
|
<property name="startDelay" value="5s" />
|
|
<!-- repeat every 5 seconds -->
|
|
<property name="repeatInterval" value="5s" />
|
|
</object></programlisting>
|
|
|
|
<para>This creates an instances of Quartz's SimpleTrigger class (as
|
|
compared to its CronTrigger class used in the previous section).
|
|
<literal>StartDelay</literal> and <literal>RepeatInterval</literal>
|
|
properties are TimeSpan objects than can be set using the convenient
|
|
strings such as 10s, 1h, etc, as supported by Spring's custom
|
|
TypeConverter for TimeSpans.</para>
|
|
|
|
<para>This trigger can then be added to the scheduler's list of registered
|
|
triggers as shown below.</para>
|
|
|
|
<programlisting language="myxml"> <object type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz">
|
|
<property name="triggers">
|
|
<list>
|
|
<ref object="cronTrigger" />
|
|
<ref object="simpleTrigger" />
|
|
</list>
|
|
</property>
|
|
</object>
|
|
</programlisting>
|
|
|
|
<para>The interleaved output of both these jobs being triggered is shown
|
|
below.</para>
|
|
|
|
<programlisting>8/8/2008 1:40:18 PM: DoAdminWork called, user name: Gabriel
|
|
8/8/2008 1:40:20 PM: ExecuteInternal called, user name: Alexandre, next fire time 8/8/2008 1:40:40 PM
|
|
8/8/2008 1:40:23 PM: DoAdminWork called, user name: Gabriel
|
|
8/8/2008 1:40:28 PM: DoAdminWork called, user name: Gabriel
|
|
8/8/2008 1:40:33 PM: DoAdminWork called, user name: Gabriel
|
|
8/8/2008 1:40:38 PM: DoAdminWork called, user name: Gabriel
|
|
8/8/2008 1:40:40 PM: ExecuteInternal called, user name: Alexandre, next fire time 8/8/2008 1:41:00 PM
|
|
8/8/2008 1:40:43 PM: DoAdminWork called, user name: Gabriel
|
|
8/8/2008 1:40:48 PM: DoAdminWork called, user name: Gabriel
|
|
8/8/2008 1:40:53 PM: DoAdminWork called, user name: Gabriel
|
|
8/8/2008 1:40:58 PM: DoAdminWork called, user name: Gabriel
|
|
8/8/2008 1:41:00 PM: ExecuteInternal called, user name: Alexandre, next fire time 8/8/2008 1:41:20 PM
|
|
8/8/2008 1:41:03 PM: DoAdminWork called, user name: Gabriel
|
|
</programlisting>
|
|
</section>
|
|
</chapter> |