Spring 2.0 introduced abstractions for asynchronous execution and scheduling of tasks. The key interfaces for scheduling and task execution are as listed as TaskExecutor, TaskScheduler, Trigger, TriggerContext and ScheduledFuture. Let take a look at each of these interfaces. This article explores spring’s scheduler related APIs in detail. You can read the official explanation for this API’s here.
follow us on @twitter and @facebook
- Spring Framework Books
- Spring Tutorials ( Collection for Spring reference tutorials)
- Spring Framework Interview Questions
- Introduction to Spring LDAP
- How to write Custom Spring Callback Methods?
TaskExecutor
TaskExecutor was introduced as an abstraction for dealing with executors. Executors are the Java 5 name for the concept of thread pools. The primary aim of TaskExecutor is to abstract away the need for Java 5 when using thread pools. The interface has only a single method as shown below:
public interface TaskExecutor extends java.util.concurrent.Executor { void execute(Runnable task); }
TaskExecutor Implementation Classes
- SimpleAsyncTaskExecutor: Does not reuse threads. It starts a new thread and is asynchronus.
- SyncTaskExecutor: No thread reuse and is synchonous. Instead, each invocation takes place in the calling thread.
- ConcurrentTaskExecutor: Exposes the Java 5 java.util.concurrent.Executor.
- SimpleThreadPoolTaskExecutor: It is a subclass of Quartz’s SimpleThreadPool which listens to Spring’s lifecycle callbacks.
- ThreadPoolTaskExecutor: It exposes bean properties for configuring a ThreadPoolExecutor configuration and and wraps it in a TaskExecutor.
- 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: This implementation uses the CommonJ WorkManager as its backing implementation
TaskScheduler
This interface has a variety of methods for scheduling tasks to run at some point in the future, as seen below:
public interface TaskScheduler { ScheduledFuture schedule(Runnable task, Trigger trigger); ScheduledFuture schedule(Runnable task, Date startTime); ScheduledFuture scheduleAtFixedRate(Runnable task, Date startTime, long period); ScheduledFuture scheduleAtFixedRate(Runnable task, long period); ScheduledFuture scheduleWithFixedDelay(Runnable task, Date startTime, long delay); ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay); }
FixedRate – period will be measured from the start time
FixedDelay – period will be measured from the completion time
TaskScheduler Implementation Classes
- TimerManagerTaskScheduler: Delegates to a CommonJ TimerManager instance, typically configured with a JNDI-lookup.
- ThreadPoolTaskScheduler: Used whenever external thread management is not a requirement. Internally, it delegates to a ScheduledExecutorService instance.
Trigger
Using Trigger the execution times may be determined based on past execution outcomes or even arbitrary conditions. The Trigger interface is as follows:
public interface Trigger { Date nextExecutionTime(TriggerContext triggerContext); }
TriggerContext is an interface and encapsulates all of the relevant data.
Trigger Implementation Classes
- CronTrigger: It enables the scheduling of tasks based on cron expressions.
- PeriodicTrigger: It 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.
Bootstrapping the scheduler
Since Spring 3.0, XML namespace for configuring TaskExecutor and TaskScheduler instances is available. It also provides a convenient way to configure tasks to be scheduled with a trigger. Add the following schema to the spring configuration file(xml file):
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd
Task Namespace
Add the following configuration :
<task:executor id="executor" pool-size="8-25" queue-capacity="100" /> <task:scheduler id="scheduler" pool-size="10" />
- task:executor – Create instance of ThreadPoolTaskExecutor
- task:scheduler – Create instance of ThreadPoolTaskScheduler
- pool-size – If the value is not provided, then the default thread pool will only have a single thread.
- queue-capacity – Number of tasks held back. Default value is Unbound
- rejection-policy – This another attribute not mentione the above example. Used for to throw exception when a task is rejected. Its default value is AbortPolicy. Other possbile values are – DiscardPolicy , DiscardOldestPolicy , and CallerRunsPolicy.
Scheduling the Tasks
Tasks can be scheduled in the following three ways:
- Annotation Driven
- XML Driven
- Programmatically
1. Annotation Driven
The @Scheduled annotation can be added to a method along with trigger metadata for task scheduling. The @Async annotation can be provided on a method so that invocation of that method will occur asynchronously.
Add following to your spring configuration file:
<context:component-scan annotation-config="true" base-package="com.javabeat"/> <task:annotation-driven executor="executor" scheduler="scheduler" />
The following example will only execute on weekdays.:
@Scheduled(cron="*/5 * * * * MON-FRI") public void doSomeTask(){ // some task that should execute on weekdays only }
Scheduled methods must have void returns and must not expect any arguments.
Syntax for @Async annotation is:
@Async void doSomething() { // this will be executed asynchronously }
2. XML Driven
Add the following configuration to the spring configuration file :
<task:scheduled-tasks scheduler="sampleScheduler"> <task:scheduled ref="someObject" method="someMethod" fixed-delay="5000"/> </task:scheduled-tasks>
3. Programmatically
Go for programmatic way when your application desire more control on scheduling. For example :
ThreadPoolTaskScheduler scheduler = (ThreadPoolTaskScheduler) appContext.getBean("scheduler"); CronTrigger trigger = new CronTrigger("*/5 * * * * MON-FRI"); ScheduledFuture<Object> scedulefuture= scheduler.schedule(taskObject, trigger );
In the above example instead of schedule() method, you can use scheduleAtFixedRate(.. , ..) or scheduleWithFixedDelay(.. , ..).
Summary
In this post we saw the basics of task execution and scheduling in Spring. We studied the interfaces TaskExecutor, TaskScheduler, and Trigger and their implementation classes. We also saw methods of scheduling the tasks, annotation driven, XML driven and programmatically. In the next article I shall demonstrate this with an example. If you are interested in receiving the future articles, please subscribe here. follow us on @twitter and @facebook.