官术网_书友最值得收藏!

Stateful Session Beans

In contrast to stateless session beans, stateful session beans maintain state for an individual client over one or more method requests. A stateful session bean is not shared among clients, and a client's reference to a bean only ends when the client ends the session or the session times out. The state is not written to a database but held in the containers cache and is lost when the container crashes.

The classic example of a stateful session bean is the online shopping cart. The user adds one or more items to a shopping cart, possibly over a long time period while the user visits other web sites or is interrupted by a phone call. Finally the user may decide to purchase the items in the cart, cancel his or her shopping cart session, or even abandon the session without explicitly terminating it.

The following example illustrates some aspects of a shopping cart. Our shopping cart will be limited to adding items to a cart and listing the current contents of a cart. First we define a remote interface as follows:

@Remote
stateful session beansexamplepublic interface ShoppingCart {
public void initialize();
public void addItem(String item);
public Collection<String> getItems();
public void finished();
}

The initialize() method performs initialization; we shall see what this means shortly. The addItem() method adds an item to the cart. The getItems() method returns the current contents of the cart. The finished() method is invoked when the client has finished their session and typically removes the session bean, so allowing the container to reclaim resources.

Next we look at the bean implementation:

@Stateful
public class ShoppingCartBean implements ShoppingCart {
private ArrayList<String> items;
@PostConstruct
public void initialize() {
items = new ArrayList<String>();
}
public void addItem(String item) {
items.add(item);
}
public Collection<String> getItems() {
return items;
}
@Remove
public void finished() {
System.out.println(
"Remove method finished() Invoked");
}
}

First note that we have used the @Stateful annotation to indicate this is a stateful session bean. We have used a @PostConstruct method, initialize(), to create an ArrayList named items. Stateful session beans may contain instance variables, such as items, which are modified by the bean. The reason, of course, is that the state of such variables is preserved from one method invocation to another. As with stateless beans we can also have a @PreDestroy method, although we have not created one in this example. The addItem() and getItems() methods are straightforward and need no further comment.

We use the @Remove annotation to indicate that after the annotated method has executed, the client no longer needs the session. The container can then delete the bean instance. If a @PreDestroy method exists, it will be executed after the @Remove method. Typically the method would perform tidying up such as closing connections. In our example the finished() method merely prints a message.

It is not compulsory to have a @Remove annotated method, but it is a good practice. Without such a method the bean instance will continue to occupy the container's cache until a timeout period is reached. At this point the bean instance is deleted by the container. The timeout period is configured by the container's administrator. By having a @Remove annotated method we are freeing up container resources as soon as we have made use of them.

The listing below shows a possible client:

public class Client {
@EJB
private static ShoppingCart shoppingCart;
public static void main(String args[]) throws Exception {
shoppingCart.addItem("Bread");
shoppingCart.addItem("Milk");
shoppingCart.addItem("Tea");
System.out.println("Contents of your cart are:");
Collection<String> items = shoppingCart.getItems();
for (String item : items) {
System.out.println(item);
}
shoppingCart.finished();
}
}

Stateful Session Bean's LifeCycle

The following state diagram shows the stateful session bean's lifecycle:

Stateful Session Bean's LifeCycle

The lifecycle of a stateful session bean differs from that of a stateless session bean in a number of respects. There is no pool of identical bean instances, as each instance serves a single client. A stateful session bean transitions from a does-not-exist to a method-ready state as soon as a client performs a business interface lookup or a dependency injection of a bean. So this step is client, and not container initiated. Once a stateful session bean is in a method-ready state, the container performs the same steps as with a method-ready stateless session bean:

  1. The bean is instantiated.
  2. The container injects the bean's SessionContext, if applicable.
  3. The container performs any other dependency injection that is specified in the bean's metadata.
  4. The container then invokes a PostConstruct callback method if one is present in the bean.

The container then calls a business method on the bean.

Recall that a session can involve considerable idle time if a client decides to wait, or perform other activities, between method calls. The container's cache could become full of idle stateful session bean instances. To limit such instances, the container can swap these from the cache out to disk or other storage. This process is called passivation and involves serialization of the bean instance. When the client decides to invoke a method on a passivated bean, then the container deserializes the saved state and invokes the requested method. This process is known as activation. Note that the method may not be on the original bean instance, but this is safe as at activation we restore the state which was saved at passivation.

The passivation algorithm is container-dependent, and typically is dependent on factors such as the maximum number of beans which may be held in the containers cache, the maximum bean idle time, and the victim selection policy of the container. The GlassFish victim selection policy has the following options: Least Recently Used (LRU), Not Recently Used (NRU), and First In First Out (FIFO). All of these factors can be configured by the container administrator.

The bean can provide a @PrePassivate callback method, which is executed immediately before passivation and a @PostActivate callback method, which is executed immediately after activation. A session bean's state may contain open resources such as open sockets, database or JMS connections that cannot be handled by the container during passivation. In these cases the resource will be closed in the @PrePassivate method and reopened in the @PostActivate method.

A bean can move from a method-ready state to a does-not-exist state if a @Remove annotated method is invoked. A bean can also do this if a container configured timeout period has been reached. In either case a @PreDestroy annotated method is first invoked.

A passivated bean can also move to a does-not-exist state if a timeout period has been reached. Note in this case any @PreDestroy annotated method will not be invoked.

The listing below shows a modified implementation of ShoppingCartBean with the @PrePassivate and @PostActivate callback methods added. The methods simply print out corresponding messages.

@Stateful
public class ShoppingCartBean implements ShoppingCart {
private ArrayList<String> items;
@PostConstruct
public void initialize() {
items = new ArrayList<String>();
}
public void addItem(String item) {
items.add(item);
}
public Collection<String> getItems() {
return items;
}
@PrePassivate public void logPassivation() { System.out.println( "PrePassivate method logPassivation() Invoked"); } @PostActivate public void logActivation() { System.out.println( "PostActivate method logActivation() Invoked"); }
@Remove
public void finished() {
System.out.println(
"Remove method finished() Invoked");
}
}

Note that there can be at most only one PrePassivate and one PostActivate method. The methods can take any name but must be void with no arguments.

Note that to simulate bean idle time, and hence conditions for passivation and activation, we have added a delay of 59 seconds between method calls from the Client:

public class Client {
public static void main(String args[]) throws Exception {
...
shoppingCart.addItem("Bread");
shoppingCart.addItem("Milk");
Thread.sleep(59000);
shoppingCart.addItem("Tea");
}
}

To test activation and passivation with GlassFish you will also need to log in as a container administrator and set the Max Cache Size to say 2. The Cache Resize quantity, which is the number of beans to passivate when the cache is full, is set to 2 and the Cache Idle Timeout to say 15 seconds. Then execute 3 simultaneous client sessions. This process may be different for other EJB containers.

主站蜘蛛池模板: 揭阳市| 通河县| 库伦旗| 吉林市| 辽宁省| 合水县| 马尔康县| 台州市| 库伦旗| 玉林市| 卓尼县| 富阳市| 昭觉县| 涿州市| 武穴市| 两当县| 成安县| 济源市| 华宁县| 墨江| 洞口县| 桃园县| 潜江市| 沅陵县| 青川县| 会昌县| 中山市| 焦作市| 三门峡市| 宝丰县| 平潭县| 青阳县| 灵璧县| 牡丹江市| 沂水县| 宝山区| 大化| 阿勒泰市| 乐昌市| 元江| 廊坊市|