diff --git a/doc/reference/src/quartz-quickstart.xml b/doc/reference/src/quartz-quickstart.xml new file mode 100644 index 00000000..41420c88 --- /dev/null +++ b/doc/reference/src/quartz-quickstart.xml @@ -0,0 +1,226 @@ + + + Quartz QuickStart + +
+ Introduction + + 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 a 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 web site. Spring + integration allows you to use Spring to configure Quartz jobs, triggers, + and schedulers and also provides integration with Spring's transaction + management features. + + 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 + IJob interface represents the task you would like + to execute. You either directly implement Quartz's + IJob interface or a convenience base class. The + Quartz ITrigger controls when a job is executed, + for example in the wee hours of the morning every weekday (This would be + done using Quartz's CronTrigger 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 JobDetail class combines the + IJob and this hashtable of data. Instead of a + generic hashtable the class JobDataMap is used. + Triggers are registered with a Quartz IScheduler + implementation that manages the overall execution of the triggers and + jobs. The implementation StdSchedulerFactory is + generally used. +
+ +
+ Application Overview + + The sample application has two types of Jobs. One that inherits from + Spring's convenience base class QuartzJobObject 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, and these triggers are in turn registered with a scheduler. In + each case the job implementation will write information to the + console. +
+ +
+ Standard job scheduling + + The Spring base class QuartzJobObject + implements IJob and allows for your object's + properties to be set via values that are stored inside Quartz's + JobDataMap that is passed along each time your job + is instantiated due a trigger firing. This class is shown below + + 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()); + } + + } + + The method ExecuteInternal is called when the + trigger fires and is where you would put your business logic. The + JobExecutionContext 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 + ExampleJob is configured by creating a + JobDetail object as shown below in the following + XML snippet taken from spring-objects.xml + + <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 throgh JobDataMap --> + <property name="JobDataAsMap"> + <dictionary> + <entry key="UserName" value="Alexandre" /> + </dictionary> + </property> + </object> + + The dictionary property of the + JobDetailObject, + JobDataAsMap, 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. + + We then will schedule this job to be executed on 20 second + increments of every minute as shown below using Spring's + CronTriggerObject which creates a Quartz + CronTrigger. + + <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> + + Lastly, we schedule this trigger with the scheduler as shown + below + + <object type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz"> + <property name="triggers"> + <list> + <ref object="cronTrigger" /> + </list> + </property> + </object> + + Running this configuration will produce the following output + + 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 +
+ +
+ Scheduling arbitrary methods as jobs + + 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. + + 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); + } + } + + Note that it does not inherit from any base class. To instruct + Spring to create a JobDetail object for this method + we use Spring's factory object class + MethodInvokingJobDetailFactoryObject as shown + below + + <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> + + + Note that AdminSerivce object is configured + using Spring as you would do normally, without consideration for Quartz. + The trigger associated with the jobDetail object is listed below + + <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> + + This creates an instances of Quartz's SimpleTrigger class (as + compared to its CronTrigger class used in the previous section. StartDelay + and RepeatInterval properties are TimeSpan objects than can be set using + the convenient strings such as 10s, 1h, etc, as supported by Spring's + custom TypeConverter. + + This trigger can then be added to the scheduler's list of registered + triggers as shown below. + + <object type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz"> + <property name="triggers"> + <list> + <ref object="cronTrigger" /> + <ref object="simpleTrigger" /> + </list> + </property> + </object> + + + The interleaved output of both these jobs being triggered is shown + below. + + 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 + +
+
\ No newline at end of file