The Benefits of Stateful Session Beans
- Introducing Stateful Session Beans
- MusicCart Stateful Session Bean
- Value List Iterator Pattern
- Web Component Client
- Local Interfaces
- Design Guidelines and Patterns
- Key Point Summary
Topics in This Chapter
- Introducing Stateful Session Beans
- Implications of Stateful vs. Stateless EJBs
- Leveraging your EJB Components
- Extending Multiple Interfaces
- Value List Iterator Pattern
- Example with a JSP Client
- Local Interfaces
In the previous two chapters, we explored the design of stateless session beans. The most important characteristic of a stateless session bean is that it does not retain client-specific data. Thus, multiple clients can share stateless session beans, providing performance benefits. Stateless session beans also provide important business processes, but the results are transient, even during a session. Although a method of a stateless session bean could keep track of client-specific data, the bean does not retain the data when the method returns. Hence, the EJB container is free to assign the same instance of a stateless session bean to another client. All instances of a stateless session bean are therefore identical.
In contrast, stateful session beans do keep track of client-specific data. Multiple clients cannot share stateful session beans because the EJB container assigns a specific instance to each client. Stateful session beans have the advantage of being tightly coupled with clients, but there is more overhead involved. It's important, therefore, to understand how to properly design applications with stateful session beans so that performance does not suffer.
In this chapter, we'll look closely at stateful session beans and show you their benefits and costs over stateless session beans. We'll also discuss how the EJB container manages stateful session beans in a J2EE environment.
5.1 Introducing Stateful Session Beans
A stateful session bean keeps track of client-specific data over the course of a session. The client-related data is stored in instance variables of the stateful session bean. The lifetime of the bean corresponds to one client's session and its state reflects the work performed throughout the session. The session bean keeps track of the conversational state between the client and the bean. Throughout its lifetime, the EJB container assigns an instance of a stateful session bean to a single client. The state of any given instance is dependent on how the client creates the bean and the invocation of its business methods. When the session terminates, the bean's state is released and the bean's instance no longer exists.
Stateful Session Passivation and Activation
In a J2EE environment, a running application uses many system resources. The EJB container, which controls the life cycle and activation state of its enterprise beans, may need to reacquire resources used by a stateful session bean. These resources include system memory, socket connections, and database connections. When resources must be reclaimed, the container serializes a bean's state and copies it to secondary storage. This process is called passivation. When it's time to restore a bean to its active state, the container reads the bean's state from secondary storage and de-serializes the objects. This process is called activation. In general, the EJB container performs this work quietly and transparently.
It's not always possible for the EJB container to serialize all state information in a session bean. If an instance variable, for example, does not implement the Serializableinterface, the container cannot save and restore the data. In this case (and in other scenarios which might require special attention), the bean developer provides code to reinitialize the bean properly.
The session bean interface provides the ejbPassivate() and ejbActi-vate()methods, which allow bean developers to control the passivation and activation tasks for a session bean. The container invokes ejbPassivate()just before it passivates the instance and ejbActivate() just after it activates the instance. The bean developer places the code for these methods in the session bean implementation class.
Let's look at an example. Suppose a stateful session bean contains an instance variable (ds) which is a reference to a DataSourceobject. To properly passivate this instance, we must assign null to the ds reference in ejbPassi-vate(), since a reference to an object cannot be serialized. To activate the instance, we provide the code to reinitialize the dsreference in ejbActivate(). The following code snippets show how to do this.
// example ejbPassivate() inside bean implementation class public void ejbPassivate() { // DataSource ds is an instance variable ds = null; } // example ejbActivate() inside bean implementation class public void ejbActivate() { String dbName = "java:comp/env/jdbc/MusicDB"; try { InitialContext ic = new InitialContext(); // DataSource ds is an instance variable ds = (DataSource) ic.lookup(dbName); } catch (Exception ex) { throw new EJBException("Cannot find DataSource: " + ex.getMessage()); } }
Design Guideline
In general, you should design an ejbPassivate() method to "undo" (or release) any actions (or resources) performed (or acquired) by the ejbActivate() method. For example, close a database connection in ejbPassivate() if you acquire it in ejbActivate().
The astute reader will recognize part of this code from our Music EJB session bean in Chapter 4, specifically the ejbCreate() method found in the Music-Bean implementation class (see its source on page 100). Why didn't we need ejbPassivate()and ejbActivate()methods for the Music EJB session bean? Recall that Music EJB is a stateless session bean. The EJB container never needs to passivate it. Once a client returns from a method invocation, the container may assign the instance to another client. This sharing means that expensive resources are more easily distributed among various clients. Furthermore, if the container needs to recover resources, it simply destroys the instance. There is no "conversational state" to save. Thus, there is no need to save and restore state through passivation and activation.
Design Guideline
When you're choosing between a stateful or stateless session bean to implement a business process, it helps to understand how the EJB container manages different session beans. A knowledge of each bean's life cycle is one way to gauge the performance impact to your enterprise application.
How does the EJB container decide which stateful bean to passivate? Usually, a container uses heuristics based on how recently a client has accessed a bean (typically the container will passivate the bean that has been called the least recently). Furthermore, if the bean is in the middle of a method call or involved in a transaction, the container cannot passivate it. (A transaction defines the boundaries of uninterruptible database operations. We discuss transactions in Chapter 6.) This chapter will demonstrate two stateful session beans by building on previous designs from earlier chapters. Our first example, a MusicCart EJB, implements the (now traditional) online shopping paradigm. A client creates a shopping cart of music recordings, adds or removes recordings from the cart, and displays the cart's contents.
Our second stateful session bean implements the Value List Iterator Pattern. This pattern is extremely useful for managing large lists of data. We'll modify our stateless session Music EJB slightly and reuse the MusicDAO from the previous chapter to access the Music Collection database. You will see that our implementation takes advantage of the performance differences between stateful and stateless session beans, leveraging the different benefits of each one to fit our application.