Creating and using programmatic timers

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.

Getting ready

There are two basic steps needed to create a programmatic timer:

  1. Using a TimerService instance to create the timer, and
  2. Declaring a callback method using the @Timeout annotation

    As 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.

How to do it...

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:

  • First argument A long number specifying the number of milliseconds to wait until the timer event occurs
  • Second argument A TimerConfig object containing timer configuration information

Use 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

How it works...

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.

There's more...

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:

  • Single event The event occurs only once
  • Interval events Events occur at regular recurring intervals
  • Calendar events Events occur based on the value of a ScheduleExpression

In addition, the getTimer method allows us to obtain a list of currently scheduled timers for the EJB.

Single event timers

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);

Interval event timers

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);

Calendar event timers

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.

Getting a collection of scheduled timers

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]

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.226.185.87