diff --git a/spring-framework-reference/src/scheduling.xml b/spring-framework-reference/src/scheduling.xml index fe24813ce3..024bf5a413 100644 --- a/spring-framework-reference/src/scheduling.xml +++ b/spring-framework-reference/src/scheduling.xml @@ -1,217 +1,183 @@ - +"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"> - Task Execution and Scheduling -
- Introduction - - The Spring Framework provides abstractions for asynchronous execution and scheduling of tasks - with the TaskExecutor and TaskScheduler - interfaces, respectively. Spring also features implementations of those interfaces that support - thread pools or delegation to CommonJ within an application server environment. Ultimately - the use of these implementations behind the common interfaces abstracts away the differences - between Java SE 5, Java SE 6 and Java EE environments. - - - Spring also features integration classes for supporting scheduling with the - Timer, part of the JDK since 1.3, and the Quartz Scheduler - (). Both of those schedulers - are set up using a FactoryBean with optional references - to Timer or Trigger instances, respectively. - Furthermore, a convenience class for both the Quartz Scheduler and the Timer is - available that allows you to invoke a method of an existing target object - (analogous to the normal MethodInvokingFactoryBean operation). - -
+ Task Execution and Scheduling -
- The Spring <interfacename>TaskExecutor</interfacename> abstraction +
+ Introduction - Spring 2.0 introduces a new abstraction for dealing with - executors. Executors are the Java 5 name for the concept of - thread pools. The "executor" naming is due to the fact that there - is no guarantee that the underlying implementation is actually a - pool; an executor may be single-threaded or even synchronous. - Spring's abstraction hides implementation details between - Java SE 1.4, Java SE 5 and Java EE environments. + The Spring Framework provides abstractions for asynchronous + execution and scheduling of tasks with the + TaskExecutor and + TaskScheduler interfaces, respectively. + Spring also features implementations of those interfaces that support + thread pools or delegation to CommonJ within an application server + environment. Ultimately the use of these implementations behind the common + interfaces abstracts away the differences between Java SE 5, Java SE 6 and + Java EE environments. - Spring's TaskExecutor interface is - identical to the java.util.concurrent.Executor - interface. In fact, its primary reason for existence is to abstract away - the need for Java 5 when using thread pools. The interface has a single - method execute(Runnable task) that accepts a task - for execution based on the semantics and configuration of the thread pool. - The TaskExecutor was originally - created to give other Spring components an abstraction for thread pooling where - needed. Components such as the ApplicationEventMulticaster, - JMS's AbstractMessageListenerContainer, - and Quartz integration all use the TaskExecutor - abstraction to pool threads. However, if your beans need thread pooling behavior, - it is possible to use this abstraction for your own needs. - -
- <interfacename>TaskExecutor</interfacename> types - There are a number of pre-built implementations of - TaskExecutor included with the - Spring distribution. In all likelihood, you shouldn't ever - need to implement your own. - - - - - SimpleAsyncTaskExecutor - + Spring also features integration classes for supporting scheduling + with the Timer, part of the JDK since 1.3, and the + Quartz Scheduler (). Both of those + schedulers are set up using a FactoryBean + with optional references to Timer or + Trigger instances, respectively. Furthermore, a + convenience class for both the Quartz Scheduler and the + Timer is available that allows you to invoke a + method of an existing target object (analogous to the normal + MethodInvokingFactoryBean operation). +
- - This implementation does not reuse any threads, - rather it starts up a new thread for each - invocation. However, it does support a - concurrency limit which will block any - invocations that are over the limit until a slot - has been freed up. If you're looking for true - pooling, keep scrolling further down the page. - - - - - - SyncTaskExecutor - +
+ The Spring <interfacename>TaskExecutor</interfacename> + abstraction - - This implementation doesn't execute - invocations asynchronously. Instead, each - invocation takes place in the calling thread. It - is primarily used in situations where - multithreading isn't necessary such as simple - test cases. - - - - - - ConcurrentTaskExecutor - + Spring 2.0 introduces a new abstraction for dealing with executors. + Executors are the Java 5 name for the concept of thread pools. The + "executor" naming is due to the fact that there is no guarantee that the + underlying implementation is actually a pool; an executor may be + single-threaded or even synchronous. Spring's abstraction hides + implementation details between Java SE 1.4, Java SE 5 and Java EE + environments. - - This implementation is a wrapper for a Java 5 - java.util.concurrent.Executor. - There is an alternative, - ThreadPoolTaskExecutor, - that exposes the Executor - configuration parameters as bean properties. It - is rare to need to use the ConcurrentTaskExecutor - but if the - ThreadPoolTaskExecutor - isn't robust enough for your needs, the - ConcurrentTaskExecutor - is an alternative. - - - - - - SimpleThreadPoolTaskExecutor - - - - This implementation is actually a subclass of - Quartz's SimpleThreadPool - which listens to Spring's lifecycle callbacks. - This is typically used when you have a - thread pool that may need to be shared by both - Quartz and non-Quartz components. - - + Spring's TaskExecutor interface is + identical to the java.util.concurrent.Executor + interface. In fact, its primary reason for existence is to abstract away + the need for Java 5 when using thread pools. The interface has a single + method execute(Runnable task) that accepts a task + for execution based on the semantics and configuration of the thread + pool. - - - ThreadPoolTaskExecutor - - - - - It is not possible to use any backport or - alternate versions of the - java.util.concurrent - package with this implementation. Both Doug - Lea's and Dawid Kurzyniec's implementations - use different package structures which will - prevent them from working correctly. - - + The TaskExecutor was originally + created to give other Spring components an abstraction for thread pooling + where needed. Components such as the + ApplicationEventMulticaster, JMS's + AbstractMessageListenerContainer, and Quartz + integration all use the TaskExecutor + abstraction to pool threads. However, if your beans need thread pooling + behavior, it is possible to use this abstraction for your own + needs. - - This implementation can only be used in a Java 5 - environment but is also the most commonly used - one in that environment. It exposes bean properties for - configuring a - java.util.concurrent.ThreadPoolExecutor - and wraps it in a TaskExecutor. - If you need something advanced such as a - ScheduledThreadPoolExecutor, - it is recommended that you use a - ConcurrentTaskExecutor - instead. - - - - - - TimerTaskExecutor - +
+ <interfacename>TaskExecutor</interfacename> types - - This implementation uses a single - TimerTask - as its backing implementation. It's different - from the - SyncTaskExecutor - in that the method invocations are executed in a - separate thread, although they are synchronous - in that thread. - - - - - - WorkManagerTaskExecutor - - - - CommonJ is a set of specifications jointly - developed between BEA and IBM. These - specifications are not Java EE standards, but - are standard across BEA's and IBM's - Application Server implementations. - + There are a number of pre-built implementations of + TaskExecutor included with the Spring + distribution. In all likelihood, you shouldn't ever need to implement + your own. - - This implementation uses the CommonJ WorkManager - as its backing implementation and is the central - convenience class for setting up a CommonJ - WorkManager reference in a Spring context. - Similar to the - SimpleThreadPoolTaskExecutor, - this class implements the WorkManager - interface and therefore can be used directly as - a WorkManager as well. - - + + + SimpleAsyncTaskExecutor - -
+ This implementation does not reuse any threads, rather it + starts up a new thread for each invocation. However, it does support + a concurrency limit which will block any invocations that are over + the limit until a slot has been freed up. If you're looking for true + pooling, keep scrolling further down the page. +
-
- Using a <interfacename>TaskExecutor</interfacename> - Spring's TaskExecutor implementations - are used as simple JavaBeans. In the example below, we define - a bean that uses the ThreadPoolTaskExecutor - to asynchronously print out a set of messages. + + SyncTaskExecutor - This implementation doesn't execute invocations + asynchronously. Instead, each invocation takes place in the calling + thread. It is primarily used in situations where multithreading + isn't necessary such as simple test cases. + + + + ConcurrentTaskExecutor + + This implementation is a wrapper for a Java 5 + java.util.concurrent.Executor. There is an + alternative, ThreadPoolTaskExecutor, that + exposes the Executor configuration parameters + as bean properties. It is rare to need to use the + ConcurrentTaskExecutor but if the ThreadPoolTaskExecutor + isn't robust enough for your needs, the + ConcurrentTaskExecutor is an + alternative. + + + + SimpleThreadPoolTaskExecutor + + This implementation is actually a subclass of Quartz's + SimpleThreadPool which listens to Spring's + lifecycle callbacks. This is typically used when you have a thread + pool that may need to be shared by both Quartz and non-Quartz + components. + + + + ThreadPoolTaskExecutor + + + It is not possible to use any backport or alternate versions + of the java.util.concurrent package with + this implementation. Both Doug Lea's and Dawid Kurzyniec's + implementations use different package structures which will + prevent them from working correctly. + + + This implementation can only be used in a Java 5 environment + but is also the most commonly used one in that environment. It + exposes bean properties for configuring a + java.util.concurrent.ThreadPoolExecutor and + wraps it in a TaskExecutor. If you + need something advanced such as a + ScheduledThreadPoolExecutor, it is + recommended that you use a ConcurrentTaskExecutor + instead. + + + + TimerTaskExecutor + + This implementation uses a single + TimerTask as its backing implementation. It's + different from the SyncTaskExecutor + in that the method invocations are executed in a separate thread, + although they are synchronous in that thread. + + + + WorkManagerTaskExecutor + + + CommonJ is a set of specifications jointly developed between + BEA and IBM. These specifications are not Java EE standards, but + are standard across BEA's and IBM's Application Server + implementations. + + + This implementation uses the CommonJ WorkManager as its + backing implementation and is the central convenience class for + setting up a CommonJ WorkManager reference in a Spring context. + Similar to the SimpleThreadPoolTaskExecutor, + this class implements the WorkManager interface and therefore can be + used directly as a WorkManager as well. + + +
+ +
+ Using a <interfacename>TaskExecutor</interfacename> + + Spring's TaskExecutor + implementations are used as simple JavaBeans. In the example below, we + define a bean that uses the + ThreadPoolTaskExecutor to asynchronously print + out a set of messages. + + import org.springframework.core.task.TaskExecutor; public class TaskExecutorExample { @@ -236,41 +202,43 @@ public class TaskExecutorExample { } public void printMessages() { - for(int i = 0; i < 25; i++) { + for(int i = 0; i < 25; i++) { taskExecutor.execute(new MessagePrinterTask("Message" + i)); } } -}]]> - - As you can see, rather than retrieving a thread from the - pool and executing yourself, you add your Runnable - to the queue and the TaskExecutor - uses its internal rules to decide when the task gets executed. - - To configure the rules that the TaskExecutor - will use, simple bean properties have been exposed. - - - - - - +} - - -]]> + As you can see, rather than retrieving a thread from the pool and + executing yourself, you add your Runnable to the + queue and the TaskExecutor uses its + internal rules to decide when the task gets executed. -
-
+ To configure the rules that the + TaskExecutor will use, simple bean + properties have been exposed. -
- The Spring <interfacename>TaskScheduler</interfacename> abstraction + <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> + <property name="corePoolSize" value="5" /> + <property name="maxPoolSize" value="10" /> + <property name="queueCapacity" value="25" /> +</bean> - In addition to the TaskExecutor - abstraction, Spring 3.0 introduces a TaskScheduler - with a variety of methods for scheduling tasks to run at some point in the future. - - +
+
+ +
+ The Spring <interfacename>TaskScheduler</interfacename> + abstraction + + In addition to the TaskExecutor + abstraction, Spring 3.0 introduces a + TaskScheduler with a variety of methods for + scheduling tasks to run at some point in the future. + + public interface TaskScheduler { ScheduledFuture schedule(Runnable task, Trigger trigger); @@ -284,42 +252,44 @@ public class TaskExecutorExample { ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay); -}]]> +} - The simplest method is the one named 'schedule' that takes a - Runnable and Date - only. That will cause the task to run once after the specified time. All of - the other methods are capable of scheduling tasks to run repeatedly. The - fixed-rate and fixed-delay methods are for simple, periodic execution, but - the method that accepts a Trigger is much more flexible. + The simplest method is the one named 'schedule' that takes a + Runnable and Date + only. That will cause the task to run once after the specified time. All + of the other methods are capable of scheduling tasks to run repeatedly. + The fixed-rate and fixed-delay methods are for simple, periodic execution, + but the method that accepts a Trigger is much more flexible. -
- The <interfacename>Trigger</interfacename> interface +
+ The <interfacename>Trigger</interfacename> interface - The Trigger interface is - essentially inspired by JSR-236, which, as of Spring 3.0, has not yet - been officially implemented. The basic idea of the - Trigger is that execution times may be - determined based on past execution outcomes or even arbitrary - conditions. If these determinations do take into account the outcome of - the preceding execution, that information is available within a - TriggerContext. The - Trigger interface itself is quite - simple: - The Trigger interface is + essentially inspired by JSR-236, which, as of Spring 3.0, has not yet + been officially implemented. The basic idea of the + Trigger is that execution times may be + determined based on past execution outcomes or even arbitrary + conditions. If these determinations do take into account the outcome of + the preceding execution, that information is available within a + TriggerContext. The + Trigger interface itself is quite + simple: + + public interface Trigger { Date nextExecutionTime(TriggerContext triggerContext); -}]]> +} - As you can see, the TriggerContext - is the most important part. It encapsulates all of the relevant data, - and is open for extension in the future if necessary. The - TriggerContext is an interface (a - SimpleTriggerContext implementation is used by - default). Here you can see what methods are available for - Trigger implementations. - As you can see, the TriggerContext + is the most important part. It encapsulates all of the relevant data, + and is open for extension in the future if necessary. The + TriggerContext is an interface (a + SimpleTriggerContext implementation is used by + default). Here you can see what methods are available for + Trigger implementations. + + public interface TriggerContext { Date lastScheduledExecutionTime(); @@ -327,336 +297,356 @@ public class TaskExecutorExample { Date lastCompletionTime(); -}]]> -
+} +
-
- <interfacename>Trigger</interfacename> implementations +
+ <interfacename>Trigger</interfacename> implementations - Spring provides two implementations of the - Trigger interface. The most interesting - one is the CronTrigger. It enables the - scheduling of tasks based on cron expressions. For example the - following task is being scheduled to run 15 minutes past each hour but - only during the 9-to-5 "business hours" on weekdays. - + Spring provides two implementations of the + Trigger interface. The most interesting + one is the CronTrigger. It enables the scheduling + of tasks based on cron expressions. For example the following task is + being scheduled to run 15 minutes past each hour but only during the + 9-to-5 "business hours" on weekdays. - The other out-of-the-box implementation is a - PeriodicTrigger that accepts a fixed period, an - optional initial delay value, and a boolean to indicate whether the - period should be interpreted as a fixed-rate or a fixed-delay. Since - the TaskScheduler interface already - defines methods for scheduling tasks at a fixed-rate or with a - fixed-delay, those methods should be used directly whenever possible. - The value of the PeriodicTrigger implementation - is that it can be used within components that rely on the - Trigger abstraction. For example, it may - be convenient to allow periodic triggers, cron-based triggers, and even - custom trigger implementations to be used interchangeably. Such a - component could take advantage of dependency injection so that such - Triggers could be configured externally. - -
+ scheduler.schedule(task, new CronTrigger("* 15 9-17 * * MON-FRI")); -
- <interfacename>TaskScheduler</interfacename> implementations + The other out-of-the-box implementation is a + PeriodicTrigger that accepts a fixed period, an + optional initial delay value, and a boolean to indicate whether the + period should be interpreted as a fixed-rate or a fixed-delay. Since the + TaskScheduler interface already defines + methods for scheduling tasks at a fixed-rate or with a fixed-delay, + those methods should be used directly whenever possible. The value of + the PeriodicTrigger implementation is that it can + be used within components that rely on the + Trigger abstraction. For example, it may + be convenient to allow periodic triggers, cron-based triggers, and even + custom trigger implementations to be used interchangeably. Such a + component could take advantage of dependency injection so that such + Triggers could be configured + externally. +
- As with Spring's TaskExecutor - abstraction, the primary benefit of the - TaskScheduler is that code relying on - scheduling behavior need not be coupled to a particular scheduler - implementation. The flexibility this provides is particularly relevant - when running within Application Server environments where threads - should not be created directly by the application itself. For such - cases, Spring provides a - TimerManagerTaskScheduler that delegates to a - CommonJ TimerManager instance, typically configured with a JNDI-lookup. - +
+ <interfacename>TaskScheduler</interfacename> + implementations - A simpler alternative, the - ThreadPoolTaskScheduler, can be used whenever - external thread management is not a requirement. Internally, it - delegates to a ScheduledExecutorService - instance. ThreadPoolTaskScheduler actually - implements Spring's TaskExecutor - interface as well, so that a single instance can be used for - asynchronous execution as soon as possible as well - as scheduled, and potentially recurring, executions. -
-
+ As with Spring's TaskExecutor + abstraction, the primary benefit of the + TaskScheduler is that code relying on + scheduling behavior need not be coupled to a particular scheduler + implementation. The flexibility this provides is particularly relevant + when running within Application Server environments where threads should + not be created directly by the application itself. For such cases, + Spring provides a TimerManagerTaskScheduler that + delegates to a CommonJ TimerManager instance, typically configured with + a JNDI-lookup. -
- The Task Namespace + A simpler alternative, the + ThreadPoolTaskScheduler, can be used whenever + external thread management is not a requirement. Internally, it + delegates to a ScheduledExecutorService + instance. ThreadPoolTaskScheduler actually + implements Spring's TaskExecutor + interface as well, so that a single instance can be used for + asynchronous execution as soon as possible as well + as scheduled, and potentially recurring, executions. +
+
- Beginning with Spring 3.0, there is an XML namespace for configuring - TaskExecutor and - TaskScheduler instances. It also provides a - convenient way to configure tasks to be scheduled with a trigger. +
+ The Task Namespace -
- The 'scheduler' element - The following element will create a - ThreadPoolTaskScheduler instance with the - specified thread pool size. - ]]> + Beginning with Spring 3.0, there is an XML namespace for configuring + TaskExecutor and + TaskScheduler instances. It also provides a + convenient way to configure tasks to be scheduled with a trigger. - The value provided for the 'id' attribute will be used as the - prefix for thread names within the pool. The 'scheduler' element is - relatively straightforward. If you do not provide a 'pool-size' attribute, - the default thread pool will only have a single thread. There are no - other configuration options for the scheduler. -
+
+ The 'scheduler' element -
- The 'executor' element - The following will create a - ThreadPoolTaskExecutor instance: - ]]> - + The following element will create a + ThreadPoolTaskScheduler instance with the + specified thread pool size. - As with the scheduler above, the value provided for the 'id' - attribute will be used as the prefix for thread names within the pool. - As far as the pool size is concerned, the 'executor' element supports - more configuration options than the 'scheduler' element. For one thing, - the thread pool for a ThreadPoolTaskExecutor is - itself more configurable. Rather than just a single size, an executor's - thread pool may have different values for the core - and the max size. If a single value is provided - then the executor will have a fixed-size thread pool (the core and max - sizes are the same). However, the 'executor' element's 'pool-size' attribute - also accepts a range in the form of "min-max". - <task:scheduler id="scheduler" pool-size="10"/> + + The value provided for the 'id' attribute will be used as the + prefix for thread names within the pool. The 'scheduler' element is + relatively straightforward. If you do not provide a 'pool-size' + attribute, the default thread pool will only have a single thread. There + are no other configuration options for the scheduler. +
+ +
+ The 'executor' element + + The following will create a + ThreadPoolTaskExecutor instance: <task:executor id="executor" pool-size="10"/> + + As with the scheduler above, the value provided for the 'id' + attribute will be used as the prefix for thread names within the pool. + As far as the pool size is concerned, the 'executor' element supports + more configuration options than the 'scheduler' element. For one thing, + the thread pool for a ThreadPoolTaskExecutor is + itself more configurable. Rather than just a single size, an executor's + thread pool may have different values for the core + and the max size. If a single value is provided + then the executor will have a fixed-size thread pool (the core and max + sizes are the same). However, the 'executor' element's 'pool-size' + attribute also accepts a range in the form of "min-max". <task:executor id="executorWithPoolSizeRange" pool-size="5-25" - queue-capacity="100"/>]]> - + queue-capacity="100"/> - As you can see from that configuration, a 'queue-capacity' value - has also been provided. The configuration of the thread pool should - also be considered in light of the executor's queue capacity. For the - full description of the relationship between pool size and queue - capacity, consult the documentation for - ThreadPoolExecutor. - The main idea is that when a task is submitted, the executor will first - try to use a free thread if the number of active threads is currently - less than the core size. If the core size has been reached, then the - task will be added to the queue as long as its capacity has not yet - been reached. Only then, if the queue's capacity - has been reached, will the executor create a new - thread beyond the core size. If the max size has also been reached, - then the executor will reject the task. + As you can see from that configuration, a 'queue-capacity' value + has also been provided. The configuration of the thread pool should also + be considered in light of the executor's queue capacity. For the full + description of the relationship between pool size and queue capacity, + consult the documentation for ThreadPoolExecutor. + The main idea is that when a task is submitted, the executor will first + try to use a free thread if the number of active threads is currently + less than the core size. If the core size has been reached, then the + task will be added to the queue as long as its capacity has not yet been + reached. Only then, if the queue's capacity has + been reached, will the executor create a new thread beyond the core + size. If the max size has also been reached, then the executor will + reject the task. - By default, the queue is unbounded, but this - is rarely the desired configuration, because it can lead to - OutOfMemoryErrors if enough tasks are added to - that queue while all pool threads are busy. Furthermore, if the queue - is unbounded, then the max size has no effect at all. Since the - executor will always try the queue before creating a new thread beyond - the core size, a queue must have a finite capacity for the thread pool - to grow beyond the core size (this is why a fixed size - pool is the only sensible case when using an unbounded queue). + By default, the queue is unbounded, but this + is rarely the desired configuration, because it can lead to + OutOfMemoryErrors if enough tasks are added to + that queue while all pool threads are busy. Furthermore, if the queue is + unbounded, then the max size has no effect at all. Since the executor + will always try the queue before creating a new thread beyond the core + size, a queue must have a finite capacity for the thread pool to grow + beyond the core size (this is why a fixed size pool + is the only sensible case when using an unbounded queue). - In a moment, we will review the effects of the keep-alive setting - which adds yet another factor to consider when providing a pool size - configuration. First, let's consider the case, as mentioned above, when - a task is rejected. By default, when a task is rejected, a thread pool - executor will throw a TaskRejectedException. - However, the rejection policy is actually configurable. The exception - is thrown when using the default rejection policy which is the - AbortPolicy implementation. For applications - where some tasks can be skipped under heavy load, either the - DiscardPolicy or - DiscardOldestPolicy may be configured instead. - Another option that works well for applications that need to throttle - the submitted tasks under heavy load is the - CallerRunsPolicy. Instead of throwing an - exception or discarding tasks, that policy will simply force the thread - that is calling the submit method to run the task itself. The idea is - that such a caller will be busy while running that task and not able to - submit other tasks immediately. Therefore it provides a simple way to - throttle the incoming load while maintaining the limits of the thread - pool and queue. Typically this allows the executor to "catch up" on the - tasks it is handling and thereby frees up some capacity on the queue, - in the pool, or both. Any of these options can be chosen from an - enumeration of values available for the 'rejection-policy' attribute on - the 'executor' element. - In a moment, we will review the effects of the keep-alive setting + which adds yet another factor to consider when providing a pool size + configuration. First, let's consider the case, as mentioned above, when + a task is rejected. By default, when a task is rejected, a thread pool + executor will throw a TaskRejectedException. + However, the rejection policy is actually configurable. The exception is + thrown when using the default rejection policy which is the + AbortPolicy implementation. For applications + where some tasks can be skipped under heavy load, either the + DiscardPolicy or + DiscardOldestPolicy may be configured instead. + Another option that works well for applications that need to throttle + the submitted tasks under heavy load is the + CallerRunsPolicy. Instead of throwing an + exception or discarding tasks, that policy will simply force the thread + that is calling the submit method to run the task itself. The idea is + that such a caller will be busy while running that task and not able to + submit other tasks immediately. Therefore it provides a simple way to + throttle the incoming load while maintaining the limits of the thread + pool and queue. Typically this allows the executor to "catch up" on the + tasks it is handling and thereby frees up some capacity on the queue, in + the pool, or both. Any of these options can be chosen from an + enumeration of values available for the 'rejection-policy' attribute on + the 'executor' element. + + <task:executor id="executorWithCallerRunsPolicy" pool-size="5-25" queue-capacity="100" - rejection-policy="CALLER_RUNS"/>]]> -
+ rejection-policy="CALLER_RUNS"/> +
-
- The 'scheduled-tasks' element +
+ The 'scheduled-tasks' element - The most powerful feature of Spring's task namespace is the - support for configuring tasks to be scheduled within a Spring - Application Context. This follows an approach similar to other - "method-invokers" in Spring, such as that provided by the JMS namespace - for configuring Message-driven POJOs. Basically a "ref" attribute can - point to any Spring-managed object, and the "method" attribute provides - the name of a method to be invoked on that object. Here is a simple - example. - - - + The most powerful feature of Spring's task namespace is the + support for configuring tasks to be scheduled within a Spring + Application Context. This follows an approach similar to other + "method-invokers" in Spring, such as that provided by the JMS namespace + for configuring Message-driven POJOs. Basically a "ref" attribute can + point to any Spring-managed object, and the "method" attribute provides + the name of a method to be invoked on that object. Here is a simple + example. -]]> + <task:scheduled-tasks scheduler="myScheduler"> + <task:scheduled ref="someObject" method="someMethod" fixed-delay="5000"/> +</task:scheduled-tasks> - As you can see, the scheduler is referenced by the outer element, - and each individual task includes the configuration of its trigger - metadata. In the preceding example, that metadata defines a periodic - trigger with a fixed delay. It could also be configured with a - "fixed-rate", or for more control, a "cron" attribute could be provided - instead. Here's an example featuring these other options. - - - - +<task:scheduler id="myScheduler" pool-size="10"/> -]]> -
-
+ As you can see, the scheduler is referenced by the outer element, + and each individual task includes the configuration of its trigger + metadata. In the preceding example, that metadata defines a periodic + trigger with a fixed delay. It could also be configured with a + "fixed-rate", or for more control, a "cron" attribute could be provided + instead. Here's an example featuring these other options. -
- Annotation Support for Scheduling and Asynchronous Execution + <task:scheduled-tasks scheduler="myScheduler"> + <task:scheduled ref="someObject" method="someMethod" fixed-rate="5000"/> + <task:scheduled ref="anotherObject" method="anotherMethod" cron="*/5 * * * * MON-FRI"/> +</task:scheduled-tasks> - Spring 3.0 also adds annotation support for both task scheduling - and asynchronous method execution. +<task:scheduler id="myScheduler" pool-size="10"/> +
+
-
- The @Scheduled Annotation +
+ Annotation Support for Scheduling and Asynchronous + Execution - The @Scheduled annotation can be added to a method along with - trigger metadata. For example, the following method would be invoked - every 5 seconds with a fixed delay, meaning that the period will be - measured from the completion time of each preceding invocation. - Spring 3.0 also adds annotation support for both task scheduling and + asynchronous method execution. + +
+ The @Scheduled Annotation + + The @Scheduled annotation can be added to a method along with + trigger metadata. For example, the following method would be invoked + every 5 seconds with a fixed delay, meaning that the period will be + measured from the completion time of each preceding invocation. + + @Scheduled(fixedDelay=5000) public void doSomething() { // something that should execute periodically -}]]> - If a fixed rate execution is desired, simply change the property - name specified within the annotation. The following would be executed - every 5 seconds measured between the successive start times of each - invocation. - + + If a fixed rate execution is desired, simply change the property + name specified within the annotation. The following would be executed + every 5 seconds measured between the successive start times of each + invocation. + + @Scheduled(fixedRate=5000) public void doSomething() { // something that should execute periodically -}]]> - If simple periodic scheduling is not expressive enough, then a - cron expression may be provided. For example, the following will only - execute on weekdays. - + + If simple periodic scheduling is not expressive enough, then a + cron expression may be provided. For example, the following will only + execute on weekdays. + + @Scheduled(cron="*/5 * * * * MON-FRI") public void doSomething() { // something that should execute on weekdays only -}]]> - Notice that the methods to be scheduled must have void returns - and must not expect any arguments. If the method needs to interact with - other objects from the Application Context, then those would typically - have been provided through dependency injection. +} - - Make sure that you are not initializing multiple instances - of the same @Scheduled annotation class at runtime, unless you do - want to schedule callbacks to each such instance. Related to this, - make sure that you do not use @Configurable on bean classes which - are annotated with @Scheduled and registered as regular Spring beans - with the container: You would get double initialization otherwise, - once through the container and once through the @Configurable aspect, - with the consequence of each @Scheduled method being invoked twice. - -
+ Notice that the methods to be scheduled must have void returns and + must not expect any arguments. If the method needs to interact with + other objects from the Application Context, then those would typically + have been provided through dependency injection. -
- The @Async Annotation + + Make sure that you are not initializing multiple instances of + the same @Scheduled annotation class at runtime, unless you do want to + schedule callbacks to each such instance. Related to this, make sure + that you do not use @Configurable on bean classes which are annotated + with @Scheduled and registered as regular Spring beans with the + container: You would get double initialization otherwise, once through + the container and once through the @Configurable aspect, with the + consequence of each @Scheduled method being invoked twice. + +
- The @Async annotation can be provided on a method so that - invocation of that method will occur asynchronously. In other words, - the caller will return immediately upon invocation and the actual - execution of the method will occur in a task that has been submitted to - a Spring TaskExecutor. In the simplest case, the annotation may be - applied to a void-returning method. +
+ The @Async Annotation - The @Async annotation can be provided on a method so that + invocation of that method will occur asynchronously. In other words, the + caller will return immediately upon invocation and the actual execution + of the method will occur in a task that has been submitted to a Spring + TaskExecutor. In the simplest case, the annotation may be applied to a + void-returning method. + + @Async void doSomething() { // this will be executed asynchronously -}]]> +} - Unlike the methods annotated with the @Scheduled annotation, - these methods can expect arguments, because they will be invoked - in the "normal" way by callers at runtime rather than from a - scheduled task being managed by the container. For example, the - following is a legitimate application of the @Async annotation. - - Unlike the methods annotated with the @Scheduled annotation, these + methods can expect arguments, because they will be invoked in the + "normal" way by callers at runtime rather than from a scheduled task + being managed by the container. For example, the following is a + legitimate application of the @Async annotation. + + @Async void doSomething(String s) { // this will be executed asynchronously -}]]> +} - Even methods that return a value can be invoked asynchronously. - However, such methods are required to have a Future typed return value. - This still provides the benefit of asynchronous execution so that the - caller can perform other tasks prior to calling 'get()' on that Future. - - returnSomething(int i) { + Even methods that return a value can be invoked asynchronously. + However, such methods are required to have a Future typed return value. + This still provides the benefit of asynchronous execution so that the + caller can perform other tasks prior to calling 'get()' on that + Future. + + @Async +Future<String> returnSomething(int i) { // this will be executed asynchronously -}]]> -
+}
+
-
- The <annotation-driven> Element +
+ The <annotation-driven> Element - To enable both @Scheduled and @Async annotations, simply - include the 'annotation-driven' element from the task namespace in - your configuration. - + To enable both @Scheduled and @Async annotations, simply include + the 'annotation-driven' element from the task namespace in your + configuration. - + <task:annotation-driven executor="myExecutor" scheduler="myScheduler"/> -}]]> +<task:executor id="myExecutor" pool-size="5"/> - Notice that an executor reference is provided for handling - those tasks that correspond to methods with the @Async annotation, - and the scheduler reference is provided for managing those methods - annotated with @Scheduled. -
-
+<task:scheduler id="myScheduler" pool-size="10"/>} -
- Using the OpenSymphony Quartz Scheduler - 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 - . For convenience purposes, - Spring offers a couple of classes that simplify the usage of Quartz within - Spring-based applications. - -
- Using the JobDetailBean - - 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: - - - - - - - - -]]> - 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: - Notice that an executor reference is provided for handling those + tasks that correspond to methods with the @Async annotation, and the + scheduler reference is provided for managing those methods annotated + with @Scheduled. +
+
+ +
+ Using the OpenSymphony Quartz Scheduler + + 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 . For convenience + purposes, Spring offers a couple of classes that simplify the usage of + Quartz within Spring-based applications. + +
+ Using the JobDetailBean + + 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 { @@ -671,123 +661,152 @@ public class ExampleJob extends QuartzJobBean { } protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException { - ]]>// do the actual work// 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). -
-
- Using the <classname>MethodInvokingJobDetailFactoryBean</classname> - Often you just need to invoke a method on a specific object. Using the - MethodInvokingJobDetailFactoryBean you can do exactly this: - - - -]]> - The above example will result in the doIt method being called on the - exampleBusinessObject method (see below): - + + 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). +
+ +
+ Using the + <classname>MethodInvokingJobDetailFactoryBean</classname> + + 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// properties and collaborators public void doIt() { - ]]>// do the actual work// do the actual work } -}]]> +} - ]]> - 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. - - - - -]]> - - By default, jobs will run in a concurrent fashion. - -
-
- Wiring up jobs using triggers and the <classname>SchedulerFactoryBean</classname> - - We've created job details and jobs. We've also reviewed the convenience bean - that allows you to 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="exampleBusinessObject" class="examples.ExampleBusinessObject"/> - - - - -]]> - 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: - - - - - - - -]]> - - 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. - -
-
+ 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. -
- Using JDK Timer support - - The other way to schedule jobs in Spring is to use JDK - Timer objects. You can create custom timers or - use the timer that invokes methods. Wiring timers is done using the - TimerFactoryBean. - -
- Creating custom timers - - Using the TimerTask you can create customer - timer tasks, similar to Quartz jobs: - - 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> + + + By default, jobs will run in a concurrent fashion. + +
+ +
+ Wiring up jobs using triggers and the + <classname>SchedulerFactoryBean</classname> + + We've created job details and jobs. We've also reviewed the + convenience bean that allows you to 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. +
+
+ +
+ Using JDK Timer support + + The other way to schedule jobs in Spring is to use JDK + Timer objects. You can create custom timers or use + the timer that invokes methods. Wiring timers is done using the + TimerFactoryBean. + +
+ Creating custom timers + + Using the TimerTask you can create customer + timer tasks, similar to Quartz jobs: + + public class CheckEmailAddresses extends TimerTask { private List emailAddresses; @@ -796,78 +815,86 @@ public class ExampleJob extends QuartzJobBean { } public void run() { - ]]>// iterate over all email addresses and archive them// iterate over all email addresses and archive them } -}]]> - - Wiring it up is simple: - - - - - test@springframework.org - foo@bar.com - john@doe.net - - - +} - - ]]><!-- wait 10 seconds before starting repeated execution --> - ]]><!-- run every 50 seconds --> - -]]> - - - Note that letting the task only run once can be done by changing the - period property to 0 (or a negative value). - - -
-
- Using the <classname>MethodInvokingTimerTaskFactoryBean</classname> - - Similar to the Quartz support, the Timer support also features - a component that allows you to periodically invoke a method: - - - - -]]> - - The above example will result in the doIt method being called on the - exampleBusinessObject (see below): - - Wiring it up is simple: + + <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" /> + <!-- run every 50 seconds --> + <property name="period" value="50000" /> + <property name="timerTask" ref="checkEmail" /> +</bean> + + Note that letting the task only run once can be done by + changing the period property to 0 (or a negative + value). +
+ +
+ Using the + <classname>MethodInvokingTimerTaskFactoryBean</classname> + + Similar to the Quartz support, the Timer + support also features a component that allows you to periodically invoke + a method: + + <bean id="doIt" class="org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean"> + <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 (see + below): + + public class BusinessObject { - ]]>// properties and collaborators// properties and collaborators public void doIt() { - ]]>// do the actual work// do the actual work } -}]]> - Changing the timerTask reference of the - ScheduledTimerTask example to the bean doIt - will result in the doIt method being executed on a fixed schedule. -
-
- Wrapping up: setting up the tasks using the <classname>TimerFactoryBean</classname> - 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. - - - - ]]><!-- see the example above --> - - -]]> -
-
+} - + Changing the timerTask reference of the + ScheduledTimerTask example to the bean + doIt will result in the doIt + method being executed on a fixed schedule. +
+ +
+ Wrapping up: setting up the tasks using the + <classname>TimerFactoryBean</classname> + + 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. + + <bean id="timerFactory" class="org.springframework.scheduling.timer.TimerFactoryBean"> + <property name="scheduledTimerTasks"> + <list> + <!-- see the example above --> + <ref bean="scheduledTask" /> + </list> + </property> +</bean> +
+
+
\ No newline at end of file