Using Stateless Session Beans

Stateless session beans are the staples of EJB systems. They offer the key benefits of J2EE—container-managed lifecycle, remote access, automatic thread safety, and transparent transaction management—with minimal overhead in performance and deployment complexity.

Benefits of Stateless Session Beans

Stateless session beans (SLSBs) are the most scalable and reliable of J2EE components for distributed apps. As we saw in , only distributed apps using stateless business objects such as SLSBs are likely to prove more scalable and robust than collocated apps. In collocated apps, SLSBs offer fewer advantages over ordinary Java classes. SLSBs are particularly well adapted to running in a cluster, as all instances are identical from the client's viewpoint. This means that incoming calls can always be routed to the best performing server. In contrast, stateful session beans are likely to encounter the problem of server affinity, where a client becomes bound to a particular server, regardless of other demand for that server. Thus stateless session bean deployments are highly reliable, even in the event of the failure of one or more server instances. WebLogic takes this to the extreme of being able to recover even in the event of a stateless session instance failing during a method invocation. Such recovery is performed by the client-side EJBObject stub if the method is identified in a WebLogic deployment descriptor as being idempotent: that is, if repeated calls to the method cannot result in duplicate updates. Since all instances are identical, an EJB container can manage a pool of stateless session beans, ensuring that thread safety can be guaranteed for each bean's business methods without blocking client access to the stateless session bean. The scalability of such stateless components with managed lifecycles has been demonstrated in platforms other than J2EE, such as Microsoft Transaction Server (MTS), which predates EJB.

The disadvantage of using stateless session beans is that they are not true objects from the client perspective (they lack identity). This poses difficulties for OO design, but unfortunately the realities of scalable enterprise architecture demand some sacrifices. As stateless session beans are often only façade objects, they can sit atop an object-oriented architecture inside the EJB tier.

Stateless Session Beans and Internal State


There's a common misconception that stateless session beans cannot hold state. They are stateless because they do not hold state between method invocations on behalf of any single client. They are free to maintain internal state—for example, to cache resources and data used on behalf of all the clients they serve.

This distinction is important, because it allows us to optimize stateless session beans by performing certain slow operations—such as the retrieval of read-only data - once and caching the results. Such data can be cached when a bean instance is created and the container invokes its ejbCreate() method, or when it is first required by a business method. EJB containers allow us to control the number of stateless session beans in the pool, meaning that we can be sure in practice that session bean instances will be reused. The size of a stateless session pool should always be less than the maximum number of threads the server is configured to permit. Maintaining a pool of more SLSB instances than the maximum number of threads wastes server resources, as it will be impossible for all the instances to be used simultaneously (this can only happen if there is one thread of execution using each SLSB instance). The point of pooling is to minimize contention for individual SLSB instances; there is no point in maintaining instances beyond the maximum number that can be used simultaneously.

Implications of Stateless Session Bean Pooling

It is through SLSB pooling that an EJB container allows us to write SLSB code as though it is single-threaded. Such pooling is efficiently implemented in J2EE app servers (although whether or not an ordinary Java object would be preferable depends on the particular case) and normally we don't need to worry about it. Occasionally, however, it is important to consider usage patterns and the implications for SLSB instance pooling when assigning operations to SLSBs. For example, suppose that grouping by use case means that a CustomerServices stateless session EJB offers a login() method as well as a performWeirdAndWonderful() method. The login() method is used heavily and requires no state to be held in the stateless session bean. On the other hand, the performWeirdAndWonderful() method is rarely invoked, but requires a lot of state to be held in the stateless session bean (that is, internal state; not state exposed to any individual client). In this case it would be better to split the CustomerServices bean into two: one would contain the frequently used login() method. As it would consume little memory, there could be a large pool of these beans. The other would contain the performWeirdAndWonderful() method. Only a single instance, or a very small pool, might be required to support the bean's usage pattern, saving memory. Occasionally it is important to understand how your EJB container performs pool management at run time for a particular class of EJB. Some servers, such as WebLogic, provide GUI tools that enable monitoring of the number of pooled instances for each deployed EJB. However, I have also found the following strategies helpful: