Jump to content

How to Use Stateless Session Bean Timers in Enterprise JavaBeans 3.1

0
  chco's Photo
Posted Nov 01 2010 07:32 PM

Below we have an excerpt from Enterprise JavaBeans 3.1, Sixth Edition. In this excerpt the author speaks to the tasks that are best suited to using Stateless Session Bean Timers.
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.

Stateless session bean timers are associated with only a specific type of session bean. When a timer for a stateless session bean goes off, the container selects an instance of that stateless bean type from the instance pool and calls its timeout callback method. This makes sense because all stateless session beans in the instance pool are logically equivalent. Any instance can serve any client, including the container itself.

Stateless session timers are often used to manage taskflow; they’re also used when the timed event applies to a collection of entities instead of just one. For example, stateless session timers might be used to audit all maintenance records to ensure that a cruise line’s ships meet state and federal guidelines. At specific intervals, a timer notifies the bean to look up the maintenance records from all the ships and generate a report. A stateless session timer can also be used to do something like send notifications to all the passengers for a particular cruise.

The stateless session bean can access an injected TimerService from the SessionContext in the @PostConstruct, @PreDestroy, or any business method, but it cannot access the Timer Service from any setter injection method. This means a client must call some method on a stateless session bean (either create or a business method) in order for a timer to be set. This is the only way to guarantee that the timer is set.

Setting a timer on the @PostConstruct method within a stateless session bean is problematic. First, there is no guarantee that an @PostConstruct callback will ever be called. We might instead use a singleton configured to eagerly load on application startup to ensure the timer is registered. An SLSB @PostConstruct callback method’s stateless session bean is called sometime after the bean is instantiated, before it enters the Method-Ready Pool. However, a container might not create a pool of instances until the first client accesses that bean, so if a client (remote or otherwise) never attempts to access the bean, the @PostConstruct callback may never be called and the timer will never be set. Another problem with using SLSB @PostConstruct is that it’s called on every instance before it enters the pool; you have to prevent subsequent instances (instances created after the first instance) from setting the timer, because the first instance created would have already done this. It’s tempting to use a static variable to avoid recreating timers, as in the following code, but this can cause problems:

public class StatelessTimerBean javax.ejb.TimedObject {

    static boolean isTimerSet = false;

    @Resource TimerService timerService;
    @Resource SessionContext ctx;

    @PostConstruct
    public void init( ){
        if( isTimerSet == false) {
            long expirationDate = (Long)ctx.lookup("expirationDate");
            timerService.createTimer(expirationDate, null );
            isTimerSet = true;
        }
    }


Although this may seem like a good solution, it works only when your application is deployed within a single server with one VM and one classloader. If you are using a clustered system, a single server with multiple VMs, or multiple classloaders (which is very common), it won’t work, because bean instances that are not instantiated in the same VM with the same classloader will not have access to the same static variable. In this scenario, it’s easy to end up with multiple timers doing the same thing. An alternative is to have @PostCreate access and remove all preexisting timers to see whether the timer is already established, but this can affect performance because it’s likely that new instances will be created and added to the pool many times, resulting in many calls to @PostCreate and, therefore, many calls to TimerService.getTimers(). Also, there is no requirement that the Timer Service work across a cluster, so timers set on one node in a cluster may not be visible to timers set on some other node in the cluster.

With stateless session beans, you should never use the @PreDestroy callback method to cancel or create timers. The @PreDestroy callback is called on individual instances before they are evicted from memory. It is not called in response to client calls to the remote or local remove method. Also, the @PreDestroy callback doesn’t correspond to an undeployment of a bean; it’s specific to only a single instance. As a result, you cannot determine anything meaningful about the EJB as a whole from a call to the ejbRemove() method, and you should not use it to create or cancel timers.

When a stateless session bean implements the javax.ejb.TimedObject interface, or contains an @javax.ejb.Timeout callback method, its lifecycle 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. Figure 19-1 shows the lifecycle of a stateless session bean that implements the TimedOut interface.

Figure 19-1. Stateless session bean lifecycle with TimedObject

Attached Image


Cover of Enterprise JavaBeans 3.1
Learn more about this topic from Enterprise JavaBeans 3.1, 6th Edition. 

Learn how to code, package, deploy, and test functional Enterprise JavaBeans with the latest edition of bestselling guide. Written by the developers of the JBoss EJB 3.1 implementation, this book brings you up to speed on each of the component types and container services in this technology, while the workbook in the second section provides several hands-on examples for putting the concepts into practice. Enterprise JavaBeans 3.1 is the most complete reference you'll find on this specification.

Learn More Read Now on Safari


Tags:
0 Subscribe


1 Reply

0
  viswamy2k's Photo
Posted Dec 01 2011 12:04 AM

Hi,
As per this if we create timer in one node1 in cluster other node2 can not fire if the node1 goes down, And i have stateless EJB timer how should i make this avaiable for all the nodes in the cluster so that node2 will fire if node1 goes go down,Could you please let me know how can do this

thanks