EJB 3.0 Timer Services - An Overview
EJB 3.0 Timer Services - An Overview
Starting from EJB 2.1, Timer Services are available for building J2EE Applications that depends
on time based services. Time based services are mostly used in scheduling applications.
Technically, these scheduling applications are called workflows. A workflow defines a
configurable sequence of activities or tasks that will take place at a particular point of time.
Before EJB 2.1, one has to manually code for building and deploying time-based workflow
systems. But, with the invent of EJB 3.0, thanks to Annotations and Dependency injections,
life has become still more easier for creating such applications.
Consider a reporting Application, that will send report in the form of mails, every Monday, or
a Billing Service that sends credit or debit bills on the 1st of every month. These
applications depend on time-based events. To be more precise, these applications should
allow developers to schedule some business logic or process so that they can be executed at
some regular intervals of time. This is the core concept behind EJB Timers.
EJB Timer Services are services that are provided by the container (or the Application
Server) and developers can take advantage of the timer services by registering one or more
enterprise beans for time-based notification.
A single action timer (or a single interval timer) is a one which will expire only once (as
opposed to interval timer, where multiple expirations are possible).
Accordingly EJB supports two different ways for constructing a single interval timer.
i) One is to create the timer in such a way that it will expire at a particular point of time
which is specified as a Date
ii) The other possible way is make the timer to expire after certain period of time (say after
10 hours or 1 day) which is usually specified in milliseconds. After the timer expires, the
enterprise bean will receive a kind of notification, i.e the container will call the ejbTimeout()
method (or the method that is annotated with @Timeout annotation).
b) Interval Timer
Interval timer (or multiple action timer), as its name suggests will recur (or happen) at
multiple intervals of time. That is, these kinds of timer will have multiple expirations at
regular intervals of time.
i) The first approach is to create a timer to have an initial expiration at some point of time
(which is usually specified as a Date) and to have the subsequent expirations happen at a
specified interval.
ii) The second approach is to construct the timer whose initial expiration will happen after
an elapsed duration of time (in milliseconds) and to have the subsequent expirations
happen after a specific interval. For every expirations of the Timer object, the container
continues to call the ejbTimeout() method (or the method that is annotated with @Timeout
annotation) until the bean explicitly calls the cancel() method.
The Timer Services API is small and has only 4 interfaces packaged with it. It is expected
that more API related to Timer Services will be added in the future EJB specification. The
interfaces are:
TimerService
Timer
TimedObject
TimerHandle
a) TimerService
This interface provides support for creating timers (single-action or interval) as well as
retrieving the existing timers (that are created by one or more enterprise beans) from the
container. Enterprise beans can use this interface for creating single-action or interval timer
objects.
Single-action Timers
The following two methods are available in the TimerService API for creating a single
action timer:
Using the first method, a single action timer can be made to expire after a specified
duration of time. The second method will be useful if the timer is needed to expire at
a particular point of time. The second argument in both the versions will be useful, if
application specific information has to be passed to the Timer objects, else it can be
safely ignored by passing null.
Interval Timers
Interval timers have options to specify the initial expiration in the form of
milliseconds or as a Date object and the subsequent expirations can be expressed in
milliseconds. In the first version, the initial expiration for the Timer object will happen
after the initialDuration has elapsed and subsequent expirations will happen at the
specified intervalDuration. The second version supports in specifying the initial time
of expiration as a Date object and the rest of the information is the same as that of
the first version. Similar to single action timers, these timers also allows the
enterprise beans to pass application specific information.
Collection getTimers() – This method will return a collection of timers that were already
created by other enterprise beans that may be in different parts of the system.
b) Time
This interface holds information about the timer objects that was previously created by
enterprise beans.
Serializable getInfo ()
Returns the application specific object that was passed previously by the enterprise
beans while creating timer objects. The object must implement the Serializable
interface.
Date getNextTimeout()
Returns the time (as a Date object) that tells when the next expiration is going to
happen for this timer object.
long getTimeRemaining()
Returns the number of remaining milliseconds that is left before the next expiration
happens for this timer.
TimerHandle getHandle()
void cancel()
Cancels the timer object. After cancellation, enterprise beans that have already
registered for getting time-based notification (through the ejbTimeout() method) will
no longer receive events.
c) TimedObject
Enterprise beans can implement this interface to receive time-based notifications (or
callbacks) on Timer objects. The ejbTimeout() method will be invoked by the container
whenever the timer expires.
For a single action timer, the ejbTimeout() will be called only once, whereas for an interval
timer, this callback method may be called multiple times.
This method is called by the EJB Container when the timer object has expired.
There are two possible ways for implementing a call back method:
One way is to make the enterprise bean implement the TimedObject interface and to
give an implementation for the ejbTimeout(Timer timer) method. For example,
@Stateless
@Remote
class MyBeanImpl implements MyBean, TimedObject{
Public void ejbTimedout(Timer timer){
.
.
}
}
The other way is to annotate a method that is defined within the enterprise bean
class with the @Timeout annotation. In this case, there is no need for the enterprise
bean to implement the TimedOut interface. The return type of this method must be
void and it should accept only one argument of type Timer.
@Stateless
@Remote
class MyBeanImpl implements MyBean{
@Timeout
public void myTimedOutMethod(Timer timer){
....
}
}
d) TimerHandle
This interface is implemented by the container so that enterprise beans at a later point can
use this handle to reconstruct the timer object. TimerHandle extends the Serializable
interface. So, the clients may serialize the handle. Because of this, TimerHandle are local
objects, hence it is illegal to pass this object as an argument to remote interfaces.
Timer getTimer()
The following summarizes the various timer operations that may happen once a timer
object is created:
Creation
Cancellation
Expiration
Timer objects are usually created by one or more enterprise beans. Only stateless
session beans and message-driven beans can create timer objects. The reason why
stateful session beans cannot create timer objects is not clear in the specification.
So, as of now, creating timer objects within stateful session beans will result in
IllegalStateException. However, it is expected that the future specifications may also
mandate stateful session beans to support timers.
a) Get a reference to the EJBContext object (for session beans it is SessionContext and
for message-driven beans, MessageDrivenContext is used).
c) Create single action or multiple Timer objects using the TimerService object.
With the new EJB 3.0 way, getting a reference to the Context object with the help of
Annotation and Dependency Injection has become easy. Following is a sample code
to get a reference to the SessionContext (in the case of session beans) and
MessageDrivenContext (in the case of message driven beans).
@Resource
@Resource
When the container creates an instance of enterprise beans, it will process all the
annotations that are listed and then perform a dependency injection. So, the result
is that sessionCtx reference and the messageDrivenCtx will be populated with an
instance of type SessionContext and MessageDrivenContext respectively.
As discussed earlier, timers are of two kinds. Single-action and Interval timer,
Depending on the requirement, create any of the two variations of the timer objects.
Given below are some samples for creating different timer objects with different
configurations.
iii) Here, the timer object initially expires after 1 week of time and subsequent
expirations will happen after two weeks of time.
iv) Here, the timer has an initial expiration that happens on the 1st of March 2007 and
subsequent expirations will happen after one week of time.
Following are the three possible ways where a timer object can be made to cancel:
When the enterprise beans decides that they no longer want to receive any kind of
notifications (via. ejbTimeout (Timer) method), then can call the cancel method in
the Timer object. Upon invoking this method, the enterprise beans that have
previously registered for getting notifications will no longer will receive callbacks(i.e
the ejbTimeout() method wont be called anymore) from the container.
.
.
timer.cancel();
Timer expiration is applicable only for single action timers (as interval timer will never
expire, the only way to stop from further functioning is to explicitly call the cancel()
method). Expiration for single action timers happen when the time (mentioned in the
form of milliseconds) has elapsed, or the time (mentioned in the form of a Date
object) duration is over.
Timer Expiration
Persistence
Timers are persistent objects. To be precise, they are permanent objects. Whenever an
enterprise bean creates an instance of a Timer object by using the TimerService, the
TimerService will persist the Timer object by storing it in a database. Even if the
server is abruptly terminated or it goes off, the timers will still be available and will
become active once the server come backs to it normal state.
Creating and canceling timers objects are made within a transactional context. So, if the
transaction rolls back after creating a timer object, then the timer object creation is
also rollbacked. Similarly, if the cancel method is called and the transaction is rolled
back subsequently, the cancellation of the timer object is also rolled back.
Sample Implementation
Given below is a sample implementation that shows how an enterprise bean can use the
facilities provided by the EJB Timer Services. Though, it is not a real time
application, it may still provide the basic concepts that are back grounding the EJB
Timer Services.
i) Scenario
This application is all about an employee who is giving status update to his manager at
regular intervals. Though, the figures (startDate, endDate and the interval duration)
and the status information may not mimic the real data, it may still provide a
valuable way for writing a simple timer based application.
a) Worker:
Since Employee and Manager are really workers in a company, the purpose of this
Worker class is to serve as a base class for the Employee and Manager class. It
contains the common properties/attributes like name and id with its associated
behavior.
b) Employee:
This class represents an employee object apart from inheriting the properties like name
and id from its base class Worker, it contains a static method getStatusString() that
randomly returns some status update message.
c) Manager:
Manager class that extends Worker class, apart from inheriting the common
functionality, provides methods like reportStatus(Employee, status) that will
accumulate the employee and his/her status information. It also has a
printEmpStatusInfo() method, that will print all the status information of the
employees for a particular duration of time.
d) StatusInfo:
StatusInfo is an information holder class that holds information about the employee and
the manager objects and also the low-level information like the startDate, endDate,
intervalDuration that will be used by the Bean for creating timer objects and
publishing status information.
e) StatusUpdateBean:
The Local and the Remote Interfaces are represented by StatusUpdateLocal and
StatusUpdateRemote respectively and the bean implementation is given by
StatusUpdateBean. The remote interface has a method called
setUpStatusInfo(StatusInfo) which is the only visible method as far as the client is
concerned. Before invoking this method, the client (whether a stand-alone client, or
a servlet ..), has to populate the StatusInfo object with relevant information like
creating some test data representing the manager/employee objects,
startDate/endDate/duration that represents when the employee has started giving
status update to his manger, till what time he has to keep giving his updates, and
the interval duration between the status updates.
f) Client:
The client gets a reference to the Remote interface through dependency injection (or
through a JNDI lookup), populates the StatusInfo object with some test objects
before calling the setUpStatusInfo(StatusInfo) method.
How it works
@Resource
// Creates a timer object using the relevant information taken from the StatusInfo
object.
// The following code creates a interval timer object with the specified startDate and
with the duration
// as its interval.
Timedout Method
One can easily figure out that the updateStatus(Timer) is the timedout method for this
enterprise bean as it is annotated with the @Timeout annotation. Within the method,
the manager and the employee objects are obtained from the StatusInfo object and
some dummy status is published to the manager object by calling the
reportStatus(Employee, status) method. The manager objects keeps on storing the
status against the employee object in a map. The method will be called infinitely if
the timer object is not cancelled, since it is an interval timer. The timer is cancelled
by checking whether the current time has crossed beyond the end time. If that’s the
case, the timer object is cancelled and the status information for the employees is
printed in the console.
Code snippet …
@Timeout
manager.reportStatus(employees.get(i), Employee.getStatusString());
if(now.after(statusInfo.getEndDate())){
manager.printEmpStatusInfo();
timer.cancel();
Conclusion
Developers can take the advantage of the EJB Timer Services for building robust
scheduling applications. One thing to remember is that, to be honest, developers are
not encouraged to depend on Timer Services for building real-time applications
(mission critical applications), as the expiration may not happen accurately at all
times because of certain factors like the network latency, underlying implementation
etc. Though, the timer services API is not exhaustive, it is believed that more and
new functionalities will be added in the next specification of the EJB.
A: EJB Timer Services are container provided services for building scheduling (time-
based) applications
Q: b) What are the two different types of Timers and how they are useful?
A: Timer comes in two forms. One is the single action timer and the other is interval
timer. The former can be used in applications wherein which some logic has to be
executed only once at a particular point of time (or after a specific duration) while
the latter can be used to execute repeated logic at regular intervals.
A: @Timeout() annotation when applied to a method will indicate that the method is a
callback method for timer expirations and the container will call this method
automatically whenever the timer object expires.
A: The createTimer() method (for both a single action and an interval timer) has an
argument called info of type Serializable. This argument can be used to pass
application specific information to timer objects (say, creditCardNumber and
expiryDate in the case of Credit Card Processing System).
A: Since timer services are container managed, we have to depend on the context
object (EJBContext to be more specific) to make use of it. For a session bean, it is a
SessionContext object and for a message driven bean, a MessageDrivenContext is
used. Then, using the Context object, obtain a reference to the TimerService object.
This TimerService factory object can then be used to create timers with different
configurations.
A: A timer object can expire when the following conditions are met.
i) When the enterprise bean, explicitly calls the cancel() method, (in this case, the
ejbTimeout(Timer) callback method will never be called.
ii) When the duration that is mentioned during the creation of the timer object has
expired, or the specified time (mentioned in the form of a Date object) has reached.
iii) The interval duration has elapsed in the case of an interval timer (in which case,
multiple expirations may be possible).