On-Demand Stateful EJBs

EJBs are the de facto standard when it comes to server-side components developed
in J2EE. Session beans are used for business logic components and are primarily of two
types: Stateful and Stateless. The type of the bean, stateful or stateless, is decided at deployment time through some deployment parameters. There are many scenarios where
the decision of needing a stateful bean can be deferred until runtime. In this article,
I will explain a pattern that can be used to dynamically choose a stateful bean at runtime.

Stateful and Stateless Session Beans

The session bean performs work for its client, shielding the client from complexity
by executing business tasks inside of the server. The stateless session bean does not hold any
conversational state with the client, and every request made to the bean needs to be accompanied
with the data required for the processing the request. Stateful session beans, on the other
hand, can hold state and support state across multiple conversations with the client.

The added convenience of stateful beans supporting conversational state comes at the cost of
performance. Stateless beans give much better performance, as they do not have client affinity.
EJB containers can pool stateless beans and can serve client requests from any bean in the pool,
in the case of stateless beans.

The choice of having a stateful or stateless bean is a design-time decision, and the deployment
descriptors of the EJB indicate the nature of the session bean to the EJB container. There is
no paradigm in which the nature of a bean can change dynamically based on the result of processing.

An Example Scenario

Consider an example scenario:
a search component needs to be developed that will allow the client to search the data store
for various parameters. A customer search will be a part of the various searches offered by the
component. If the client logs in as a particular customer, then any subsequent
searches by the component should apply the customer's profile for searches. The associated searches
could include a search for the list of products that the customer is eligible for. In the absence of a
specific customer, this search would return results for a default user of the system. For the sake of
keeping the example generic, I will not outline the specific searches but this scenario is common
to many business applications.

I will explain a pattern to provide statefulness to stateless beans dynamically
and will apply that pattern to the sample business scenario described above. The
forces that necessitate the need for such a pattern are:

There are currently only two broad classifications of session EJBs that exist.

There is no way to convert a stateless bean to a stateful bean dynamically.

Business scenarios demand a change from a stateless bean to a stateful bean based on
the result of processing at runtime.

The client should not have the burden of creating a stateful bean; it
should be handled behind the scenes.

The Pattern

I will detail a pattern that will solve the issues we have with the current scenario.
Create a focus class that is a POJO (Plain Old Java Object). The focus class will have
the implementation logic for the component that needs to be developed. Model the component as
both stateful and stateless session beans. The session bean will instantiate and use the
focus class for fulfilling client requests. The client will, by default, access the services
of the stateless bean through a delegate.
If processing the request deems that the client needs a stateful service, a stateful service is created
and the stateful service starts serving subsequent client requests. The stateful service also
uses the focus class and passes on the client's state when invoking focus class methods.

The class diagram shown in Figure 1 has the main classes that are involved in the pattern and also
shows the collaboration between the various classes.

Figure 1. Class diagram of stateless/stateful session bean pattern

Client

The client is any Java object that needs to use the services offered by the EJB component.
The client uses the delegate in order to interact with the service. The client is oblivious of the
existence of both stateful and stateless services and consumes the services offered by the EJB.

Delegate

The delegate here is a combination of a service locator as well as a business delegate pattern.
The delegate is responsible for looking up the stateless service and making calls onto the service.
The delegate is also responsible for parsing the returned dataset, storing the stateful bean's handle,
and calling on the stateful service if the handle is valid. An alternative approach is for the delegate
to parse the dataset when it's given as an input to a method, and call the stateful service if
the handle points to a valid stateful bean.

Stateless Service

The stateless service is a stateless session EJB that offers the component services to its clients.
The stateless service offers no conversational state with the client and is the bean that's looked
up by the delegate class. The stateless bean makes use of the focus class to provide functionality.

Stateful Service

The stateful service is created on the fly by the stateless service when it determines that the request
cannot be served by its stateless nature. This can be determined based on the requesting data or the
processing logic in the stateless service. The stateful service is capable of storing state on behalf
of the calling client and applies the state to any calls made on the focus class.

Dataset

The dataset is a generic return type from the server to the client. The dataset has a placeholder for
the actual data that's returned from the service as a result of the method call, and can store
metadata about the returned data to the client. The dataset will also hold the handle
to the stateful service and is used by the delegate to request data that's required
of the stateful service.

Focus Class

The focus class has the main processing logic for the component. The focus class contains the base
functionality and does not hold any state. It works on the data passed into it and holds no state
between method calls. The focus class is used by both the stateful and the stateless service. As a
rule of thumb, it's a good practice to have those methods in the focus class that are common to both
the stateful and the stateless service.

Collaborations

The client instantiates and uses the delegate in order to make any calls to the component. The delegate
has the logic to look up the stateless bean and makes the call to the corresponding method on the stateless
service. The stateless service processes the request by calling on the focus class and obtains the results.
The results of the processing are returned back to the client in the form of the dataset object.

If during the processing of the request, the stateless service determines that the service needs to store the state of the request for future processing, the stateless service creates a stateful service. The handle to the stateful bean is stored in the dataset object that's returned back to the client. The returned dataset also contains the resultant data for the client. The delegate could parse the dataset object before returning it back to the client and store the handle to the stateful bean as its state. The next time a call is made to the delegate by the client, the delegate would make a request to the stateful bean whose handle is being stored as a part of the delegate's state.

The stateful bean can use the state that it stores on behalf of the client and pass it on as an additional
attribute to the focus class. The focus class need not be concerned about whether the request was made
by the stateful service or the stateless service. The request made to the focus class from the stateful
bean will have additional state information, and hence will allow the result to reflect any conversational
state on behalf of the client. Figure 2 shows this relationship as a UML diagram.

7

Figure 2. Interaction sequence between pattern participants

Applying the Pattern

I will use the above pattern to solve the example scenario. The client will use a
delegate to use the features of the search component. The delegate will have the lookup code and will
also expose the same set of methods exposed by the service. The client invokes the searchParam1
method on the
delegate and the delegate calls the searchParam1 method of the stateless service.

If the client calls the login method, the delegate calls on the corresponding method of the
stateless service. If the search result is a single customer, the stateless service creates an instance of
the stateful service and passes the customer details to the ejbCreate method of the stateful service.
The stateless service also creates an instance of the DataSet and sets the customer data, as well as the stateful handle, to the DataSet object. The delegate stores the handle and passes on the DataSet to the client.

The client now needs to obtain the list of products associated with the customer. The client calls
the delegate's retrieveProducts method. The delegate retrieves the stateful handle that
it has and calls the associated method of the stateful bean.

The associated class stubs used for this example scenario are given in the
Resources section below.

Alternate Scenarios

The pattern is generic and can be used in a variety of applications. The pattern described above
can be used where a value list handler needs to be used. The generic searches can be done using a stateless
bean and when the result size exceeds a maximum size, we can create a stateful bean and pass back the results in the form of the dataset object. The client can approach the delegate for the next set of records and the delegate can go to the stateful bean that stores the details, such as last record processed, maximum number of objects, etc.

Related Patterns

Service Locator Pattern:
The Service Locator pattern reduces the client complexity that results from the client's
dependency on, and need to perform, lookup and creation processes, which are resource-intensive.
To eliminate these problems, this pattern provides a mechanism to abstract all dependencies and
network details into the service locator.

Business Delegate Pattern:
The Business Delegate acts as a client-side business abstraction; it provides an abstraction for,
and thus hides, the implementation of the business services. Using a Business Delegate reduces the
coupling between presentation-tier clients and the system's business services. Depending on the
implementation strategy, the Business Delegate may shield clients from possible volatility in
the implementation of the business service API. Potentially, this reduces the number of changes
that must be made to the presentation-tier client code when the business service API or its underlying
implementation changes.

Value List Handler:
The Value List Handler pattern creates a Value List Handler to control query execution functionality and
results caching. The Value List Handler directly accesses a DAO that can execute the required query.
The Value List Handler stores the results obtained from the DAO as a collection of Transfer Objects.
The client requests the Value List Handler to provide the query results as needed. The Value List Handler
implements an Iterator pattern (GoF) to provide the solution.

Conclusion

The Dynamic EJB Statefulness pattern helps model components that
exhibit both stateful and stateless behavior. A component using this
pattern delivers the performance of stateless session beans and
serves the stateful needs of clients. Clients of a component developed
using the pattern have a simple unified interface and are hidden from
the internal swap between the stateful and stateless beans. The
pattern is a natural fit with other J2EE patterns, such as Business
Delegate and Service Locator.