Lecture13 - Information Technology Gate

clumpsmackoverΛογισμικό & κατασκευή λογ/κού

2 Δεκ 2013 (πριν από 3 χρόνια και 8 μήνες)

71 εμφανίσεις

1

Timer Service


Regardless of the software, scheduling systems are used in
many different scenarios:


In a credit card processing system, credit card charges are
processed in batches so that all the charges made for an
entire day are settled together rather than separately. This
work is scheduled to be done in the evening to reduce the
impact of processing on the system.


In a hospital or clinical system, Electronic Data Interface
(EDI) software is used to send medical claims to various
HMOs. Each HMO has its own processing requirements, but
all of them are routine, so jobs are scheduled to gather
claim data, put it in the proper format, and transfer it to the
HMO.

2

Timer Service


In just about any company, managers need specific
reports run on a regular basis. A scheduling system
can be configured to run those reports automatically
and deliver them via email to managers.


In the EJB world, there has been a general interest in
scheduling systems that can work directly with
enterprise beans.


However, prior to EJB 2.1, there has been no standard
Java EE scheduling system. Enterprise JavaBeans 2.1
introduced a standardized but limited scheduling
system called the Timer Service that hasn't been
expanded at all in EJB 3.0.

3

Titan's Maintenance Timer


Titan Cruises has a policy of performing regular
maintenance on its ships.


For example, the engines require extensive and varied
maintenance activities throughout the year, as do
navigation equipment, communications, sewer and
water systems, etc.


In fact, there are literally thousands of maintenance
functions to be performed on a ship throughout the
year.


To manage all of these items, Titan uses the EJB Timer
Service to alert the proper maintenance crews when an
item needs to be serviced.


4

Timer Service API


To use the Timer Service, an enterprise bean must
implement the
javax.ejb.TimedObject
interface, which
defines a single callback method,
ejbTimeout( )
:


package javax.ejb;


public interface TimedObject {


public void ejbTimeout(Timer timer) ;

}



In EJB 3.0, the
@javax.ejb.Timeout
annotation can be
applied to a method whose signature returns
void

and has
one
javax.ejb.Timer
parameter.


For example, the Ship Maintenance EJB can be modified to
implement the
TimedObject

interface, as shown:

5

Timer Service API

@Stateless

public class ShipMaintenanceBean implements ShipMaintenanceRemote


implements javax.ejb.TimedObject {



public void ejbTimeout(javax.ejb.Timer timer) {


// business logic for timer goes here


}

}


Alternatively, the @javax.ejb.Timeout annotation can be
used:

@Stateless

public class ShipMaintenanceBean implements ShipMaintenanceRemote
{


@Timeout


public void maintenance(javax.ejb.Timer timer) {


// business logic for timer goes here


}

}

6

Timer Service API


The TimerService allows a bean to register itself for
notification on a specific date, after some period of time, or at
recurring intervals. The following code shows how a bean
would register for notification exactly 30 days from now:


// Create a Calendar object that represents the time

30 days from now.

Calendar time = Calendar.getInstance( ); // the current time.

time.add(Calendar.DATE, 30); // add 30 days to the current time.

Date date = time.getTime( );


// Create a timer that will go off 30 days from now.

TimerService timerService = // from EJBContext or injected

timerService.createTimer( date, null);



For example, a client could schedule a maintenance item for
the cruise ship Valhalla on April 2, 2006, as shown in the
following code snippet:

7

Timer Service API

InitialContext jndiCntxt = new InitialContext( );

ShipMaintenanceRemote maintenance =

(ShipMaintenanceRemote) jndiCntxt.lookup("ShipMaintenanceRemote ");

ShipMaintenanceRemote Calendar april2nd = Calendar.getInstance( );

april2nd.set(2006, Calendar.APRIL, 2);

String description = "Stress Test: Test Drive Shafts A & B ...";

maintenance.scheduleMaintenance("Valhalla", description,
april2nd.getTime( ));



The ShipMaintenanceBean implements the
scheduleMaintenance( ) method and takes care of
scheduling the event using the Timer Service, as shown
here:

8

Timer Service API

@Stateless

public class ShipMaintenanceBean implements ShipMaintenanceRemote{



@Resource javax.ejb.TimerService timerService;


@PersistenceContext(unitName="titanDB") entityManager;



public void scheduleMaintenance(String ship, String description,


Date dateOfTest) {


String item = ship + " is scheduling maintenance of " +
description;


timerService.createTimer(dateOf, msg);


}


@Timeout


public void maintenance(javax.ejb.Timer timer) {


// business logic for timer goes here


}


...

}

9

The TimerService Interface


The
TimerService

interface provides an enterprise bean
with access to the EJB container's Timer Service so that new
timers can be created and existing timers can be listed. The
TimerService
interface is part of the
javax.ejb
package in EJB 3.0 and has the following definition:

package javax.ejb;

import java.util.Date;

import java.io.Serializable;


public interface TimerService {


// Create a single
-
action


timer that

expires on a specified date.


public Timer createTimer(Date expiration, Serializable info)


throws
IllegalArgumentException,IllegalStateException,EJBException;

10

The TimerService Interface

// Create a single
-
action timer that expires after a specified
duration.


public Timer createTimer(long duration, Serializable info)


throws
IllegalArgumentException,IllegalStateException,EJBException;


// Create an interval timer that starts on a specified date.


public Timer createTimer(


Date initialExpiration, long intervalDuration, Serializable info)


throws
IllegalArgumentException,IllegalStateException,EJBException;

// Create an interval timer that starts after a specified duration.


public Timer createTimer(


long initialDuration, long intervalDuration, Serializable info)


throws
IllegalArgumentException,IllegalStateException,EJBException;


// Get all the active timers associated with this bean


public java.util.Collection getTimers( )


throws IllegalStateException,EJBException;

}

11

The TimerService Interface


Here's how each of the four createTimer( ) methods works.
At this point, we are discussing only the expiration and
duration parameters and their uses. The Serializable info
parameter is discussed later in this chapter.


createTimer(Date expiration, Serializable info)



Creates a single
-
action timer that expires once. The timer
expires on the date set for the expiration parameter. Here's
how to set a timer that expires on July 4, 2006:


Calendar july4th = Calendar.getInstance( );

july4th.set(2006, Calendar.JULY, 4);

timerService.createTimer(july4th.getTime( ), null);

12

The TimerService Interface

createTimer(long duration, Serializable info)



Creates a single
-
action timer that expires only once. The
timer expires after duration time (measured in milliseconds)
has elapsed. Here's how to set a timer that expires in 90
days:


long ninetyDays = 1000 * 60 * 60 * 24 * 90; // 90 days

timerService.createTimer(ninetyDays, null);





13

The TimerService Interface

createTimer(Date initialExpiration, long
intervalDuration, Serializable info)



Creates an interval timer that expires many times. The timer
first expires on the date set for the initialExpiration parameter.
After the first expiration, subsequent expirations occur at
intervals equal to the intervalDuration parameter (in
milliseconds).


Here's how to set a timer that expires on July 4, 2006 and
continues to expire every three days after that date:


Calendar july4th = Calendar.getInstance( );

july4th.set(2006, Calendar.JULY, 4);

long threeDaysInMillis = 1000 * 60 * 60 * 24 * 3; // 3 days

timerService.createTimer(july4th.getTime( ), threeDaysInMillis,
null);

14

The TimerService Interface

createTimer(long initialDuration, long
intervalDuration, Serializable info)



Creates an interval timer that expires many times. The timer
first expires after the period given by initialDuration has
elapsed. After the first expiration, subsequent expirations
occur at intervals given by the intervalDuration parameter.
Both initialDuration and intervalDuration are in milliseconds.
Here's how to set a timer that expires in 10 minutes and
continues to expire every hour thereafter:


long tenMinutes = 1000 * 60 * 10; // 10 minutes

long oneHour = 1000 * 60 * 60; // 1 hour

timerService.createTimer(tenMinutes, oneHour, null);

15

Exceptions


The
TimerService.getTimers( )

method can throw an
IllegalStateException
or an
EJBException
. All of the
createTimer( )

methods declare these two exceptions,
plus a third exception, the
IllegalArgumentException
.
Here are the reasons why the
TimerService

methods
would throw these exceptions:



java.lang.IllegalArgumentException


The duration and expiration parameters must have valid
values. This exception is thrown if a negative number is used
for one of the duration parameters or a null value is used for
the expiration parameter, which is of type
java.util.Date
.

16

Exceptions

java.lang.IllegalStateException


This exception is thrown if the enterprise bean attempts to
invoke one of the TimerService methods from a method where
it's not allowed.


Each enterprise bean type (i.e., entity, stateless session, and
message driven) defines its own set of allowed operations.
However, in general, the TimerService methods can be
invoked from anywhere except the EJBContext methods (i.e.,
setEntityContext( ), setSessionContext( ), and
setMessageDrivenContext( )).


javax.ejb.EJBException


This exception is thrown when some type of system
-
level
exception occurs in the Timer Service.

17

The Timer


A
Timer

is an object that implements the
javax.ejb.Timer

interface. It represents a timed event that has been scheduled
for an enterprise bean using the Timer Service.
Timer

objects
are returned by the
TimerService.createTimer( )

and
TimerService.getTimers( )

methods, and a
Timer

is
the only parameter of the
TimedObject.ejbTimeout( )

method or annotated
@javax.ejb.Timeout
callback.


The
Timer

interface is:


package javax.ejb;

public interface Timer {


// Cause the timer and all its associated expiration


// notifications to be canceled


public void cancel( )


throws
IllegalStateException,NoSuchObjectLocalException,EJBException;

18

The Timer

// Get the information associated with the timer at the time of
creation.


public java.io.Serializable getInfo( )


throws
IllegalStateException,NoSuchObjectLocalException,EJBException;



// Get the point in time at which the next timer


// expiration is scheduled to occur.


public java.util.Date getNextTimeout( )


throws
IllegalStateException,NoSuchObjectLocalException,EJBException;



// Get the number of milliseconds that will elapse


// before the next scheduled timer expiration


public long getTimeRemaining( )


throws
IllegalStateException,NoSuchObjectLocalException,EJBException;



//Get a serializable handle to the timer


public TimerHandle getHandle( )


throws
IllegalStateException,NoSuchObjectLocalException,EJBException;

}

19

Canceling timers


The previous section used the
Timer.cancel( )

method. It's used to cancel a specific timer from the
Timer Service so that it never expires.


It is useful if a particular timer needs to be removed
completely or simply rescheduled.


To reschedule a timed event, cancel the timer and
create a new one. For example, when one of the ship's
components fails and is replaced, that component must
have its maintenance rescheduled: it doesn't make
sense to perform a yearly overhaul on an engine in June
if it was replaced in May.

20

Identifying timers


Of course, comparing descriptions is a fairly unreliable way of
identifying timers, since descriptions tend to vary over time.
What is really needed is a far more robust information object
that can contain both a description and a precise identifier.


All of the
TimeService.createTimer( )

methods declare
an
info

object as their last parameter. The
info

object is
application data that is stored by the Timer Service and
delivered to the enterprise bean when its timeout callback is
invoked.


The serializable object used as the
info

parameter can be
anything, as long as it implements the
java.io.Serializable
interface and follows the rules of
serialization.
[*]

The
info

object can be put to many uses, but
one obvious use is to associate the timer with some sort of
identifier.

21

Identifying timers


For example, instead of comparing maintenance descriptions
to find duplicate timers, Titan decided to use unique
Maintenance Item Numbers (MINs). MINs and maintenance
descriptions can be combined into a new MaintenanceItem
object:


public class MaintenanceItem implements java.io.Serializable {


private long maintenanceItemNumber;


private String shipName;


private String description;


public MaintenanceItem(long min, String ship, String desc) {


maintenanceItemNumber = min;


shipName = ship;


description = desc;


}


public long getMIN( ) {


return maintenanceItemNumber;


}


public String getShipName( ) {


return shipName;


}


public String getDescription( ) {


return description;


}

}

22

Identifying timers


Using the MaintenanceItem type, we can modify the
scheduleMaintenance( ) method to be more precise, as
shown here (changes are in bold):

@Stateless

public class ShipMaintenanceBean implements ShipMaintenanceRemote {



@Resource javax.ejb.TimerService timerService;


public void scheduleMaintenance(


MaintenanceItem maintenanceItem, Date dateOfTest) {


for (Object obj : timerService.getTimers( )) {


MaintenanceItem scheduled =
(MaintenanceItem)timer.getInfo( );


if (scheduled.getMIN() == maintenanceItem.getMIN( )) {


Timer.cancel( );


}


}


}

23

Identifying timers

@Timeout


public void maintenance(javax.ejb.Timer timer) {


// business logic for timer goes here


}

}



The MaintenanceInfo class contains information about the
maintenance work that is to be done and is sent to the
maintenance system using JMS.


When one of the timers expires, the Timer Service calls the
maintenance( ) method on the Ship Maintenance EJB. When
the maintenance( ) method is called, the info object is
obtained from the Timer object and used to determine which
timer logic should be executed.

24

Exceptions


All the methods defined in the
Timer

interface declare
two exceptions:



javax.ejb.NoSuchObjectLocalException


This exception is thrown if you invoke any method on
an expired single
-
action timer or a canceled timer.



javax.ejb.EJBException


This exception is thrown when some type of system
-
level exception occurs in the Timer Service.

25

Transactions


When a bean calls
createTimer( )
, the operation is
performed in the scope of the current transaction. If the
transaction rolls back, the timer is undone: it's not created
(or, more precisely, it's uncreated).


For example, if the Ship Maintenance EJB's
scheduleMaintenance( )

method has a transaction
attribute of
RequiresNew
, a new transaction will be
created when the method is called.


If an exception is thrown by the method, the transaction rolls
back and the new timer event is not created.


In most cases, the timeout callback method on beans should
have a transaction attribute of
RequiresNew
.


This ensures that the work performed by the callback
method is in the scope of container
-
initiated transactions.

26

Stateless Session Bean Timers


Our Ship Maintenance EJB example was an example of a
stateless session bean's usage of the Timer Service.
Stateless session bean timers can be used for auditing or
batch processing .



As an auditing agent, a stateless session timer can monitor
the state of the system to ensure that tasks are being
completed and that data is consistent. This type of work
spans entities and possibly data sources. Such EJBs can also
perform batch
-
processing work such as database cleanup,
transfer of records, etc.


Stateless session bean timers can also be deployed as
agents that perform some type of intelligent work on behalf of
the organization they serve. An agent can be thought of as an
extension of an audit: it monitors the system but it also fixes
problems automatically.

27

Stateless Session Bean Timers


When a stateless session bean implements the
javax.ejb.TimedObject interface, or contains an
@javax.ejb.Timeout callback method, its life cycle
changes to include the servicing of timed events.


The Timer Service pulls an instance of the bean
from the instance pool when a timer expires; if
there are no instances in the pool, the container
creates one.


Next figure shows the life cycle of a stateless
session bean that implements the TimedOut
interface.

28

Stateless Session Bean Timers

Stateless session bean life cycle with TimedObject

29

Message
-
Driven Bean Timers


Message
-
driven bean timers are similar to stateless
session bean timers in several ways. Timers are
associated only with the type of bean.


When a timer expires, a message
-
driven bean instance is
selected from a pool to execute the timeout callback
method. In addition, message
-
driven beans can be used
for performing audits or other types of batch jobs.


The primary difference between a message
-
driven bean
timer and a stateless session bean timer is the way in
which they're initiated: timers are created in response to
an incoming message or, if the container supports it,
from a configuration file.

30

Message
-
Driven Bean Timers


In order to initialize a message
-
driven bean timer from an
incoming message, you simply put the call to the
TimerService.createTimer( ) method in the message
-
handling
method. For a JMS
-
based message
-
driven bean, the method
call goes in the onMessage( ) method:


@MessageDriven

public class JmsTimerBean implements MessageListener {


@Resource TimerService timerService

public void onMessage(Message message){


MapMessage mapMessage = (MapMessage)message;


long expirationDate = mapMessage.getLong("expirationDate");


timerService.createTimer(expirationDate, null );

}


@Timeout


public void timeout( ){


// put timeout logic here


}

31

Message
-
Driven Bean Timers


As was the case for stateless session beans, the
TimedObject interface or the presence of an
@Timeout method changes the life cycle of the
message
-
driven bean slightly.


When a timed event occurs, the container must
pull a message
-
driven bean instance from the pool.


If there are no instances in the pool, then an
instance must be moved from the Does Not Exist
state to the Method
-
Ready Pool before it can
receive the timed event.

32

Message
-
Driven Bean Timers

Message
-
driven bean lifecycle with TimedObject