- EJB 3 Developer Guide
- Michael Sikora
- 1333字
- 2021-07-02 11:34:54
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:

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:
- The bean is instantiated.
- The container injects the bean's
SessionContext
, if applicable. - The container performs any other dependency injection that is specified in the bean's metadata.
- 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.
- Enhancing Microsoft Content Management Server with ASP.NET 2.0
- HTML5 Multimedia Development Cookbook
- YUI 2.8: Learning the Library
- Instant Microsoft SQL Server Analysis Services 2012 Dimensions and Cube
- Photoshop CS6中文版從入門到精通(核心技法卷):摳圖、修圖、Camera Raw、調色、銳化、合成
- AutoCAD 2018中文版基礎教程
- ANSYS 15.0有限元分析自學手冊
- AI繪畫實戰:Midjourney從新手到高手
- 高等院校電腦美術教材:CorelDRAW X7中文版基礎教程
- 零基礎攝影后期修圖 Photoshop照片處理輕松入門
- CorelDRAW X6平面設計與制作案例教程
- 中文版SolidWorks 2018完全實戰技術手冊
- Photoshop CC中文版基礎教程
- 中文版AutoCAD 2021完全自學教程
- Adobe創意大學視頻編輯師 After Effects CS5 + Premiere Pro CS5 標準實訓教材