Timers can be created using methods of the TimerService
interface. This interface supports methods for creating timers which generate events at a specific time, after an elapsed time, after a specific interval, or according to a schedule. This approach provides the client with the ability to initiate a timer.
There are two basic steps needed to create a programmatic timer:
TimerService
instance to create the timer, andAs we will see, there are several TimerService
interface methods available to create a timer. Most of these will be explored in the There's more section of this recipe. Initially, we will use the createSingleActionTimer
method to create a simple one-time timer. When a timer is created, a callback method must be identified. With programmatic timers, the @Timeout annotation is used to mark the method as the callback method. This annotation can only be used once per class.
The simplest way of getting a TimerService
instance is to use dependency injection. In the SystemReportManager
, use the @Resource annotation to inject a TimerService
object. Also, add a long variable called duration
and initialize it to 1000.
@Resource TimerService timerService; long duration = 1000;
Next, add a method called createTimer
. The method is passed and returns void. In the method, use the TimerService
method, createSingleActionTimer
, to create a timer. This method has two arguments:
long
number specifying the number of milliseconds to wait until the timer event occurs TimerConfig
object containing timer configuration informationUse the duration
variable as the first argument and create a new TimerConfig
object as the second argument. The use of the TimerConfig
argument is explored in the Using the timer interface recipe and holds additional timer-related information.
public void createTimer() { timerService.createSingleActionTimer(duration, new TimerConfig()); }
Next, we will create a callback method called timeout
. Use the @Timeout annotation with the method. In the method, display a message indicating the method has executed and then display the value returned from the getMemoryReport
method.
@Timeout public void timeout(Timer timer) { System.out.println("timeout: timeout occurred"); System.out.println("getMemoryReport: " + getMemoryReport()); }
In the ReportsServlet
, comment out the statement which calls the getMemoryReport
method. Instead, add the following statement which calls the createTimer
method:
systemReportManager.createTimer();
Execute the ReportsServlet
. Its output should closely match the following:
INFO: timeout: timeout occurred
INFO: getMemoryReport:
Total Memory: 266604544
Maximum Memory: 518979584
Free Memory: 149822400
A TimerService
object was injected into the EJB and later used in the createTimer
method to create the timer. This createTimer
method had a duration argument of one second which meant that the timer would not fire until approximately one second after its creation. The timer method, timeout
, was designated using the @Timeout annotation. The createTimer
method was called from the ReportsServlet
.
The TimerService
interface has several methods to create timers. Each of these methods returns a Timer
object representing the timer except for the getTimers
method which returns a Collection
of Timers
. They differ in how they specify the time of the callback event.
All timers created with these methods are persistent by default. The control of a timer's persistent is detailed in the Using persistent and non-persistent timers recipe. Also, timers can be cancelled using the Timer's cancel
method.
The methods of the TimerService
interface supports three types of events:
In addition, the getTimer
method allows us to obtain a list of currently scheduled timers for the EJB.
Single event timers result in the callback method executing only once. There are two createSingleActionTimer
methods supporting this type of event. In addition, there are two createTimer
methods supporting single events.
Let's look at the createSingleActionTimer
methods first. Both of its methods have two arguments. The first argument is either a Date
object or a long
value. The second argument is a TimerConfig
object used to hold additional timer-related information.
The event will occur at the time specified by the Date
object. Using the long
argument specifies the event will occur in that number of milliseconds in the future.
To demonstrate the use of the Date
parameter, replace the body of the SystemReportManager's createTimer
method with the following code. When the code is executed, a callback should be made on January 5, 2014 at 11:12. Depending on the current time, you may or may not want to wait for this event.
GregorianCalendar reportCalendar = new GregorianCalendar(2014, Calendar.JANUARY, 5, 11, 12); Date reportDate = reportCalendar.getTime(); timerService.createSingleActionTimer(reportDate, new TimerConfig());
Like the createSingleActionTimer
, the createTimer
methods have two arguments. The first is either a Date
or a long
value and behaves the same way as the createSingleActionTimer
methods. Its second argument is a Serializable
argument whose value is associated with the timer and can be retrieved by the Timer's getInfo
method. The use of this argument is explored in the Using the timer interface recipe.
The code sequence below achieves the same result as the previous example. The Serializable
object is set to null
in this case.
GregorianCalendar reportCalendar = new GregorianCalendar(2014, Calendar.JANUARY, 5, 11, 12); Date reportDate = reportCalendar.getTime(); timerService.createTimer(reportDate, null);
The createIntervalTimer
method can also be used to create timers which execute at intervals. In addition, there are two versions of the createTimer
method that will do the same thing.
Both versions of the createIntervalTimer
method take three arguments. The first argument is either a Date
or a delay value specifying the time the first callback is to occur. The second argument is a long
value which determines the time between subsequent callbacks. The last argument is a TimerConfig
object.
The following example results in a series of callbacks which occur one second after the timer is created and are repeated every three seconds.
timerService.createIntervalTimer(1000, 3000, new TimerConfig());
Two of the createTimer
methods support the creation of interval timers. These methods also have three arguments which are the same as those of the createIntervalTimer
except for the last argument. The last argument is a Serializable
object whose value becomes part of the Timer
. The Timer's getInfo
method can be used to retrieve this information as detailed in the Using the timer interface recipe.
Here, the previous interval timer is duplicated using the createTimer
method. A null
value is passed as the Serializable
object.
timerService.createTimer(1000, 3000, null);
The callback event in a calendar-based timer is controlled by a ScheduleExpression
object. This expression is detailed in the Understanding calendar-based scheduling recipe. The overloaded createCalendarTimer
method supports the creation of this type of timer.
The first of the two overloaded methods has a single argument: ScheduleExpression
. The expression represented by this object specifies when the callback will occur. The second version of the method has two arguments with the first being the ScheduleExpression
object and the second being a TimerConfig
object which conveys additional information to the timer.
Replace the body of the createTimer
method with a call to the createCalendarTimer
method as shown below. A ScheduleExpression
is created first and initialized to January 5, 2014 at 14:7:40.
ScheduleExpression scheduleExpression = new ScheduleExpression(); scheduleExpression.year(2014); scheduleExpression.month(1); scheduleExpression.dayOfMonth(5); scheduleExpression.hour(14); scheduleExpression.minute(7); scheduleExpression.second(40); timerService.createCalendarTimer(scheduleExpression, new TimerConfig());
When the method is executed, a callback will be made at the specified time.
Periodically, it may be desirable to determine which timers have been scheduled. The TimerService's getTimers
method returns a collection of currently scheduled timers. Replace the body of the createTimer
method with the following code sequence. In this sequence, two Timer
objects are created. The first is for January 1, 2012 and the second is for January 1, 2013. This is followed by the use of the getTimers
method and a for
loop to display the timer's schedule expressions.
ScheduleExpression scheduleExpression = new ScheduleExpression(); scheduleExpression.year(2012); scheduleExpression.month(1); scheduleExpression.dayOfMonth(1); timerService.createCalendarTimer(scheduleExpression, new TimerConfig()); scheduleExpression = new ScheduleExpression(); scheduleExpression.year(2013); scheduleExpression.month(1); scheduleExpression.dayOfMonth(1); timerService.createCalendarTimer(scheduleExpression, new TimerConfig()); Collection<Timer> timers = timerService.getTimers(); for(Timer timer : timers) { System.out.println(timer.getSchedule()); }
The execution of the code will result in output similar to the following:
INFO: ScheduleExpression [second=0;minute=0;hour=0;dayOfMonth=1;month=1;dayOfWeek=*;year=2013;timezoneID=null;start=null;end=null]
INFO: ScheduleExpression [second=0;minute=0;hour=0;dayOfMonth=1;month=1;dayOfWeek=*;year=2012;timezoneID=null;start=null;end=null]
18.226.185.87