Types of Session Beans
There are two types of session beans: stateless and stateful. Stateless session beans are business objects that hold conversations that span a single client-invoked method call. They do not maintain any conversational state associated with any client. Stateful session beans are business objects that hold conversations that span multiple client-invoked method calls. Stateful session beans provide an easy and robust way to handle conversational state.
Stateless Session Beans
Stateless session beans do not maintain the conversational state associated with any client. The client is responsible for maintaining the conversational state, if any. The container could reuse the same instance to serve multiple clients. This makes perfect sense because the bean instance doesn't maintain any client specific state.
An example of stateless session bean is a stock quote component that returns the current price of a given stock symbol. Such a bean could look up the stock price from a database that is updated by a real-time feed. Another example is a stateless session bean that implements a compression algorithm. This bean accepts a plain text as a parameter and returns a compressed buffer.
The sample university registration application uses a stateless session bean to model a SignOn component to verify the user's login and password. It also allows new users to create a login and password in the system.
The remote interface SignOn is defined as follows:
public interface SignOn extends EJBObject { public void addUser(String username, String password) throws RemoteException; public boolean validateUser(String login, String password) throws InvalidLoginException, RemoteException; }
This interface contains two business methods, addUser and validateUser, which are callable by the client.
The home interface SignOnHome is defined as follows:
public interface SignOnHome extends EJBHome { SignOn create() throws CreateException, RemoteException; }
So, to create a bean instance, you call the create() method on the home interface. Notice that the create() method returns a remote interface instance (as opposed to the enterprise bean class).
The bean class SignOnEJB is defined as follows:
public class SignOnEJB implements SessionBean { private SessionContext ctx; /* --- callback methods --- */ /* container calls this method to set the associated session context */ public void setSessionContext(SessionContext c) { ctx = c; } /* container calls this method so that you can initialize your session bean instance */ public void ejbCreate() {} /* container invokes this method before it ends the life of the session object. */ public void ejbRemove() {} /* ejbActivate and ejbPassivate are not used by stateless session beans */ public void ejbActivate() {} public void ejbPassivate() {} /* ---here you implement all business methods as defined in the component interface--- */ public void addUser(String userName, String password) { /* code to add a new user to the database */ } public boolean validateUser(String userName, String password) throws InvalidLoginException { /* code to validate the user login and password from database */ } }
CAUTION
The create() method of a stateless session bean should not accept any parameters. Because a stateless session bean does not maintain any conversational state, you must make sure that none of the client-passed parameters are stored beyond the method call.
The deployment descriptor for the enterprise bean is specified as follows:
<session> <ejb-name>SignOnEJB</ejb-name> <home>SignOnHome</home> <remote>SignOn</remote> <ejb-class>SignOnEJB</ejb-class> <session-type>Stateless</session-type> ... </session>
The session element declares a session bean and an ejb-name element within the session element, which defines the session bean's name (SignOnEJB). The session element also declares other things, such as the home interface (SignOnHome), remote interface (SignOn), and bean's class (SignOnEJB). The session-type element declares this is a stateless session bean (as opposed to a stateful session bean).
Instance Pool
The creation and destruction of enterprise beans are expensive operations. To reduce this cost, the EJB container maintains an instance pool for each type of stateless session bean. At start up, the container creates instances as specified in the deployment descriptor of the stateless session bean. The EJB container may reuse the same instance to serve multiple client requests. This mechanism of multiplexing enhances the performance and response time of client interaction. Using a small number of instances in a predefined pool to satisfy a large number of clients has been proven to be a good practice for increasing performance and managing resources. The instance pool is also called the caching policy.
CAUTION
Instance pooling is applicable only to stateless session beans, not to stateful session beans.
NOTE
Two or more different clients cannot share a stateless session bean instance concurrently. They can, however, reuse the same instance that comes from the instance pool.
Stateful Session Beans
Stateful session beans maintain the state associated with a client. Stateful session bean fields contain a conversational state on behalf of the session object's client. This state describes the conversation represented by a specific client/session object pair. The conversational state is preserved across method invocations and transactions.
Unlike a stateless session bean, a stateful session object has a unique identity that is assigned by the EJB container at create time.
An example of a stateful session bean is a shopping cart that represents the collection of products selected by a particular customer for purchase during a session. The shopping cart should not be shared because it represents a particular interaction with a particular customer and is alive only for the customer's session. Also, the shopping cart is not saved into the database unless the customer is ready to place an order. Another example of a stateful session object is a trader session component that allows a trader to interactively add, remove, and place trades.
Stateful session beans are useful in workflow management that requires the bean to maintain client data over different method invocations. Behind the scenes, the bean manages the workflow of several enterprise beans. The bean mediates between the client and the other components of the application, presenting a simplified view to the client.
The sample university registration application uses stateful session beans to model enrollment cart component. An enrollment cart is similar to a shopping cart. It represents the collection of courses selected by a particular student for purchase during a session.
The remote interface EnrollmentCart is defined as follows:
public interface EnrollmentCart extends EJBObject { public void addCourses(String[] courseIds) throws RemoteException; public Collection getCourses() throws RemoteException; public void empty() throws RemoteException; }
The business methods callable by clients are defined in this interface. For example, the EnrollmentCart interface defines three business methods: addCourses (to add courses to the cart), getCourses (to retrieve the courses in the cart), and empty (to empty the enrollment cart).
The home interface EnrollmentCartHome is defined as follows:
public interface EnrollmentCartHome extends EJBHome { EnrollmentCart create() throws CreateException, RemoteException; }
So, to create a enrollment cart instance, the client calls the create() method on the home interface. The create() method returns a remote interface instance (as opposed to the enterprise bean class).
The bean class EnrollmentCartEJB is defined as follows:
public class EnrollmentCartEJB implements SessionBean { /* ctx and cart constitute the conversational state */ private SessionContext ctx; private HashSet cart; /* --- callback methods */ /* container calls this method to set the associated session context */ public void setSessionContext(SessionContext c) { ctx = c; } public void ejbCreate() throws CreateException { cart = new HashSet(); } /* This method is called when the instance is activated from its "passive" state. */ public void ejbActivate() {} /* This method is called when the container intends to passivate the bean instance. */ public void ejbPassivate() {} /* Container invokes this method before it ends the life of the session object. */ public void ejbRemove() {} /* ...here you implement all business methods as defined in the component interface... */ public void addCourses(String[] courseIds) { if ( courseIds == null) { return; } for ( int i = 0; i < courseIds.length ; i ++ ) { cart.add(courseIds[i]); } } public Collection getCourses() { return cart; } public void empty() { cart.clear(); } }
The EnrollmentCartEJB implements all the methods it defined in the EnrollmentCart interface. In addition, it implements callback methods to be implemented by any session bean.
The deployment descriptor for the enrollment cart session bean is specified as follows:
<session> <ejb-name>EnrollmentCartEJB</ejb-name> <home>EnrollmentCartHome</home> <remote>EnrollmentCart</remote> <ejb-class>EnrollmentCartEJB</ejb-class> <session-type>Stateful</session-type> ... </session>
The deployment descriptor for a stateful session bean is similar to that of a stateless session bean except for the element session-type (which is stateful in this case).
Passivation and Activation
The EJB container creates a separate stateful bean instance for each new connected client. In large e-commerce applications, the number of clients connected concurrently to a web site can be in the thousands. This can have an adverse effect on performance when resources are used up. Passivation and activation are mechanisms that are provided by the EJB container to manage these valuable resources, such as memory, in order to reduce the number of stateful session bean instances required to service all concurrent clients.
Passivation is the mechanism by which the EJB container stores the bean's state into a back store, such as the file system or a database. The container starts passivation as soon as the number of allocated stateful session beans exceeds a certain threshold.
The passivation process serializes all non-transient member variables to a persistent store. After serializing the enterprise bean state, the EJB container calls the ejbPassivate() method on the instance. In this method, you would close any resources, such as sockets, JDBC connections that you are holding.
Activation, on the other hand, is the process of restoring the bean state from the back store. The EJB container activates a passivated instance when the bean's client decides to continue interactions with the bean instance. After restoring the bean's state, the EJB container calls the ejbActivate() method on the instance. In this method, you would open any resources you need to service the client, such as sockets, JDBC connections, and so on.
For example, you can specify the threshold (maximum number of beans in the cache) in the deployment descriptor for the WebLogic server as follows:
<stateful-session-cache> <max-beans-in-cache>1000</max-beans-in-cache> </stateful-session-cache>
As new concurrent clients request the bean's services, WebLogic creates new instances of the bean. When the 1001st client requests the bean's services, the server passivates some of the idle beans (perhaps using an LRU [Least Recently Used] algorithm).
CAUTION
Passivation and activation are applicable only to stateful session beans and not to stateless session beans.