Implementing a Stateful Session Bean

When implementing a stateful Session bean, there are a number of issues that you must keep in mind. They are discussed in this section.

Passivation

Unlike stateless Session beans, stateful Session beans are at liberty to store client- specific state information in instance variables. However, because your bean may be passivated, any instance variables you define must be either primitives, references to serializable objects, or—failing that—be transient.

Of course, any transient variables will be reset to null if the bean is passivated and then re-activated, so your implementation will need to deal with this. Classes that are not serializable often depend in some way on the environment, such as an open java.net.Socket, so that your bean can act as a network client to some service. The general approach to dealing with this is to store other data that is serializable in instance variables during the ejbPassivate() method. Then, the non-serializable reference can be re-instantiated in the ejbActivate() method using this other data.

For example, in the case of a Socket, your bean could hold a String and an int representing the hostname and the port number of the socket. The instance variables and ejbActivate() method could would be something like the following:

import java.net.*;
// code omitted.

private transient Socket clientSocket;
private String socketHost;
private int socketPort;
public void ejbActivate() {
    this.clientSocket = new Socket(socketHost, socketPort);
}

Although your Session bean must itself be serializable, it is not necessary to explicitly implement the java.io.Serializable interface. This is because the javax.ejb.SessionBean interface extends from Serializable (by way of its super-interface, javax.ejb.EnterpriseBean).

Tip

Given that passivation causes quite a few implementation headaches, some commentators have asked why the EJB specification goes to such lengths to define a passivation mechanism. After all, operating systems are very good at paging memory to disk, and this is all that the “secondary storage” is really accomplishing.

These are good questions, with no ready answers. But if you would rather have the operating system do the work and keep your beans simple, just configure your beans with a very high passivation threshold.


You may be wondering how to handle passivation in a stateful Session bean that has a reference to a home or remote interface of another EJB, a javax.sql.DataSource or some other resource connection factory. After all, none of these references may be serializable. Luckily, though, the EJB specification puts the onus for worrying about these references on the EJB container (section 7.4.1). In other words, your bean is at liberty to hold references to any of these types of objects, and you don't need to care whether they are serializable. Of course, most EJB container vendors are likely to comply with this part of the specification by making sure that these objects are serializable.

Timeouts

Another difference between stateful and stateless Session beans is that stateful Session beans may timeout. If a bean is timed out, the client's reference is no longer valid, and any further invocations on that reference will result in a java.rmi.NoSuchObjectException for remote clients.

You should note from Figure 5.14 that if a bean times out, its ejbRemove() method will not be called. This means that you shouldn't adopt a convention of acquiring external resources in ejbCreate() with a view to releasing them in ejbRemove(). Even releasing the resources in ejbPassivate() is not enough, because a bean can be timed out even from its ready state.

Caution

Don't confuse passivation and timeout. An EJB container might implement passivation using an LRU strategy and allow a bean timeout to be specified in seconds. If the EJB container is not busy, a bean will not be passivated according to the LRU strategy, but it may hit its timeout nevertheless.


Chaining State

It is generally a bad idea to have more than one stateful Session bean involved in any conversation, because no matter which way you cut it, there's always the chance that one of them will time out, preventing the other from completing.

To see this, suppose the client calls stateful Session A, which, in turn, uses the services of stateful Session B. There are two cases—the timeout of A is larger than that of B, or the timeout is less than that of B. Taking each in turn

  • Suppose that the timeout of Session bean A is 30 minutes and that of Session bean B is 20 minutes. The client makes a call on A at time t1=0, which then calls B. If the client calls A at time t2 = t1 + 25 minutes, A's call to B will fail because B will have timed out.

  • Suppose now that the timeout of Session bean A is 20 minutes, and that of Session bean B is 30 minutes. The client makes a call on A at time t1=0, which then calls B. The client then calls A again at time t2 = t1 + 19 minutes, although for this call, A does not need to call B to service the request. If the client calls A again at time t3 = t2 + 19 minutes = t1 + 38 minutes, A's call to B will fail because B was last invoked more than 30 minutes ago and will have timed out.

A similar problem can occur with session beans and servlets; this is discussed on Day 12.

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

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