In This Chapter
A session bean is a synchronous Enterprise JavaBean (EJB) type that enables you to model real-world business logic in the form of a reuseable and portable J2EE component. Hence, a session bean resides completely within the context of an EJB container (WebLogic Server).
The following are the general characteristics of session beans:
From a client perspective, a session bean is a nonpersistent object that implements some business logic running on a server.
A session bean is not shared among multiple clients. It performs business logic on behalf of a single client.
Client access is mediated by the EJB container in which the bean is deployed.
The client of a session bean can be a remote client or a local client. Remote clients include Java programs (Java applications, applets, servlets, or JSPs) or non-Java clients, such as CORBA clients. Local clients include other EJBs deployed in the same JVM as the bean.
Session beans can be transaction aware.
They are not persistent, so they are relatively short lived within the EJB container. A bean’s lifespan is typically less than or equal to its client.
They do not represent data in a data store. However, they can be used to access or update such data.
In the J2EE Application Programming Model, session beans are used as process or control objects specific to a client, so they are a candidate J2EE technology for representing business logic and rules and for controlling workflow between other EJB types (entity and message-driven beans).
▸ To learn more about the J2EE Application Programming Model, see Chapter 5, “The J2EE Architecture and APIs,” p. 171.
Session beans can typically be used for processing credit card numbers, trading stocks, implementing shopping carts, and computing advanced algorithms. Overall, a session bean can be used to house rules governing tasks in a business application. Session beans are also intended to be relatively coarse-grained business objects, such as purchase orders, sales orders, or insurance claims. Fine-grained objects, such as line items on a purchase order, should not be modeled as session beans. This has more to do with session beans being remote objects and less to do with any functional limitations.
The value and importance of session beans come from the communication interface between clients and session beans. Session beans consist of a bean class and two interfaces—the home interface and the remote interface. These interfaces provide the thin client to a bean, whereas the bean class, which implements the javax.ejb.SessionBean
interface, carries out the business logic.
This implementation model allows clients to use the remote interface as a proxy to the EJB and, therefore, reduces the resource consumption and complexity that clients have to bear. In addition, the bean developer benefits by being able to focus primarily on coding business logic, while the EJB container provides the environment (bean classes and interfaces) in which the bean is implemented. As shown in Figure 20.1, at a high level, the EJB container transparently intercepts client calls to a bean’s method, injects management and control infrastructure services to the invocation, and then calls the bean’s method.
The infrastructure services that the EJB container provides to a session bean can include the following:
Java Naming and Directory Interface (JNDI) registration of the bean when deployed
Life cycle and state management
Authentication and access control through declarative or programmatic security
Serializing method calls
Bean pooling
Transaction management
Persistence management
Developers, therefore, do not have to be concerned about implementing these infrastructure services or the underlying details of how the client finds the bean or communicates with the bean. On the whole, bean developers implement business logic via methods in the session bean class, and the EJB container provides functionality for remote access, security, concurrency, transactions, and other infrastructure services the bean requires to achieve its desired behavior.
Session beans can be implemented in one of the following state management modes—stateless or stateful. The following sections discuss these bean types, their distinct differences, and their use in applications.
Stateless session beans contain no conversational state between methods for a specific client. When a client calls a method on a stateless session bean, the bean’s instance variables can contain state, but only for the duration of the call. When the method has completed, the bean instance no longer retains the state. The stateless bean instance can, however, hold state, but its state is not guaranteed to be specific to a calling client. For example, instance variables of a stateless bean instance can include an open database connection or an object reference to an EJB object.
However, when stateless bean instance are not involved in servicing a client-called method, they are all considered identical from the client’s perspective. Hence, there is no fixed mapping between clients and stateless instances. This allows the EJB container to delegate a client-called method to any available stateless bean instance. For example, the EJB container can delegate requests from the same client within the same transaction to different instances of the stateless bean between remote method calls.
In general, an EJB container needs to retain only the number of stateless bean instances required to service the current client load. Because of client “think time,” the number of stateless session beans is usually much smaller than the number of active clients. The EJB container typically tries to minimize the resources needed to support stateless session bean clients by creating and destroying the bean instance on an as-needed basis.
WebLogic Server can pool identical EJBs, such as stateless session beans and message-driven beans, increasing the J2EE application’s scalability and performance.
Stateless session beans are commonly used for procedural tasks that can be accomplished in a single client request. These tasks are sometimes referred to as Model Reuseable Service Objects—any business object providing a generic type of services to its clients. A typical example is a business task that requires returning a list of books by author. Likewise, an application requiring workflow or state management could be modeled with stateless session beans. This application might require chaining session beans to accomplish the task. Chaining stateful session beans becomes a problem when one of the session beans times out or generates an exception. For instance, if three stateful session beans are chained together and the second one in the chain times out, the state trailing the second bean instance would be lost. Because stateless session beans do not maintain conversational state, losing state would not be an issue. The EJB container would simply assign another bean instance without the client being aware of the transition.
Also, the Facade pattern is based on session beans providing a higher-level entry point into a system; what transpires in the subsystem is hidden from the client. This allows the client to access an object’s method at the entry point, thus enabling the method to carry out all underlying tasks in the subsystem. It is important to model session beans as a Facade pattern to take advantage of performance efficiencies. Because EJBs are remote objects, it is best for the client to call only the unified interface to the system, thus reducing the number of remote calls. Having session beans call individual EJB objects might not result in a remote call, as WebLogic Server is optimized to make local method calls instead of remote calls when possible.
Stateful session beans are similar to stateless session beans, except they contain conversational state on behalf of a specific client; this state must be retained across invoked methods and transactions. A stateful session bean retains a client’s conversational state by storing the state as attributes of the bean. It is the EJB container’s responsibility to ensure that subsequent method calls by a client are routed to the same instance of a stateful bean.
Stateful session beans are memory consumers because state has to be maintained within the bean instance. Therefore, to efficiently manage stateful session beans, the EJB container might need to temporarily transfer the state of an idle stateful session bean instance from memory to disk. This transfer is called instance passivation. The transfer back to memory is called activation. The container can passivate a stateful session bean instance only when the instance is not in a transaction.
A session object’s conversational state might contain open resources, such as open database connections. A container cannot retain these open resources when a session bean instance is passivated. The session bean developer must close and open resources in the ejbPassivate()
and ejbActivate()
methods.
Stateful session beans are appropriate in the following application situations:
The need to maintain client state—. Stateful session beans enable you to maintain conversational state about a specific client, so they can be used whenever a server-side business object has to represent client state information. However, because each stateful bean is tied to a client request (unlike stateless beans), it cannot be pooled, so be careful when using stateful session beans.
Representing workflow scenarios—. Business objects that manage the interaction of modules or submodules across a transaction can easily be represented as stateful beans. These objects are usually tied to a single client request and must maintain state information; these characteristics are typical of a stateful EJB.
Represent short-lived, nonpersistent objects—. Unlike entity beans, stateful beans are not persistent and generally live for the lifetime of the client request to which they are attached. They cannot be re-created after the client’s session with the server is over, and even a server failure can force the death of stateful session beans.
For example, a client’s interaction between the browser and the Web server follows the request/response model. Because HTTP is considered connectionless and stateless, after the server has responded to the client’s request the connection is dropped and forgotten. Using stateful session beans in a Web-based application provides a mechanism for storing the client’s interaction with the server. A shopping cart in an e-commerce Web site is a good example of using stateful session beans. Other examples include an ATM account transfer application, an airline reservation system, and an online book store.
Even though the major difference between stateless and stateful sessions beans is based on maintaining conversational state between the client and the bean instance, Table 20.1 compares the primary characteristics of these two bean types.
Table 20.1. Comparing Stateless and Stateful Session Beans
Stateless Session Bean | Stateful Session Bean |
---|---|
Maintains no state. | |
The same stateless session bean within the same home has the same object identity, which the container assigns. | Has a unique identity that the container assigns at create time. |
Holds no conversational state between methods for a specific client, so it can be pooled. | Holds conversational state between methods for a specific client, so it cannot be pooled. |
Not bound to a single client request. | Bound to a single client request. |
Does not make use of passivation and activation. | Passivation and activation are intricate parts of its behavior. |
Cannot implement the | Can make use of the |
No caching of conversation state. Can cache object state. | Can cache conversational state. |
Commonly used for business logic and workflow. |
Even if you are new to Enterprise JavaBeans, you should easily understand the conceptual purpose and development benefits they provide in enabling client-side business logic to exist as very portable and loosely coupled components. These components exist within the context of a robust, highly available, and performance-oriented application infrastructure, such as WebLogic Platform.
The aspect of EJBs that most people have difficulty understanding is the elements that constitute an EJB and how they exist and are carried out within the EJB container. This section of the chapter is dedicated to giving you a thorough understanding of a session bean’s structural elements, explaining how and why they are developed and deployed in the manner they are, and describing how you can call methods on a session bean from a client. The following sections are a practitioner’s approach to teaching you about session beans, so be prepared for some hands-on development.
The journey ahead will be fast-paced, as shown in Figure 20.2.
The following list expands on the items shown in Figure 20.2:
You will become familiar with the class files associated with a session bean and develop the required class files for a simple session bean example.
You will create a Java client to test the session bean after it has been deployed.
You will learn about deployment descriptors (ejb-jar.xml
and weblogic-ejb-jar.xml
) by developing them for the session bean example.
You will learn how to build an EJB deployment unit by compiling and packaging the associated class files and deployment descriptors for the session bean example into a single JAR module ready for deployment.
You will deploy your session bean application and test its operations.
As shown in Figure 20.3, it’s the bean developer’s responsibility to supply the following class files that constitute a session bean:
To provide a remote view of a session bean, you need to implement the following interfaces:
The remote view provides location independence to the session bean. For example, a client running in the same JVM as a session bean instance uses the same Java RMI API to access the bean as a client running in a different JVM on the same or different machine.
To provide a local view of a session bean, you need to implement the following interfaces:
Unlike the remote view, the local view of the session bean is not location independent. Access to the bean requires the client to be located in the same JVM as the session bean. For example, a local client of a session bean can be another enterprise bean (a session bean, an entity bean, or a message-driven bean).
The Implementation
class, which implements the bean’s actual business logic.
The Implementation
class is also commonly referred to as the SessionBean
class, as it implements all available methods in the session bean’s remote or local interfaces.
To develop a session bean, you provide the Implementation
class file plus class files for the remote view or local view interfaces—or even both. However, unless you are packaging the bean’s client in the same JAR or EAR archive file as the session bean, you need to provide only the remote view interfaces for the bean. The remote view interfaces are required to enable a client to remotely access the bean via RMI/IIOP, which is the standard communication mechanism between distributed Java and J2EE objects, for example, Java clients calling methods on Java remote objects, such as EJBs.
▸ To learn more about RMI, see Chapter 12, “Distributed Processing Using RMI,” p. 385.
Details on using local client view interfaces are discussed later in this chapter in “Using a Local View to Access a Session Bean.” First, to get you better acquainted with the composition of a session bean, the following sections discuss the class files that constitute a simple stateless session bean. This example uses the infamous HelloWorld session bean, and you’ll be creating the following class files:
examples.sessionbean.HelloWorld
(remote interface)
examples.sessionbean.HelloWorldHome
(home interface)
examples.sessionbean.HelloWorldBean
(Implementation
class)
To make sure this example is practical, you will also deploy the HelloWorld session bean to WebLogic Server and create a simple Java client to test the bean’s operation.
To set up your working environment for this session bean example, create a working directory on your file system (for example, one named Helloworld
), and then create the following subdirectories:
src
(source files—.java
).
classes
(compiled Java classes—.class
).
deployment
(deployment descriptors for the session bean—ejb-jar.xml
and weblogic-ejb.xml
).
lib
(deployment module—.jar
).
A build script, discussed later in “Building a Session Bean Deployment Unit,” uses these subdirectories to compile and package the HelloWorld session bean. However, you can create your own specific working directory and subdirectories and modify the build script accordingly.
The remote interface acts as a proxy for the session bean instance in the EJB container. The methods defined by the remote interface are literally reflections of the public methods declared in the Implementation
class. Each business method defined in the remote interface must have an identical (or counterpart) method in the Implementation
class. The business methods defined by the remote interface are what the client calls to process tasks on the session bean instance.
The class that implements a session bean’s remote interface within the EJB container is known as the session EJBObject
, which is generated at deployment. The EJBObject
class implements the methods of the javax.ejb.EJBObject
interface as well as methods specific to the Implementation
class. Within the EJB container, it is the responsibility of EJBObject
to delegate a client’s method call to the session bean instance.
The following rules must be considered when creating a remote interface for a session bean:
The remote interface must extend the javax.ejb.EJBobject
interface.
All methods must throw the java.rmi.RemoteException
exception.
Because the remote interface is a Java RMI type interface, all arguments and return values must also be valid types of RMI/IIOP.
Each method defined by the interface must match a method in the SessionBean
class—same name, number of arguments, argument types, return types, and throws
clause.
The interface and methods must be declared public.
The parameter and return values must be serializable.
Listing 20.1 shows the remote interface for the HelloWorld session bean.
Example 20.1. Remote Interface for the HelloWorld Session Bean
package examples; import java.rmi.*; import javax.ejb.*; /* The methods defined in this interface are the public interface of the * HelloWorld session bean. */ public interface HelloWorld extends EJBObject { /** * This method is identical to the one defined in the Implementation class of * the Session Bean, except this method must throw a java.rmi.RemoteException. */ public String getHelloWorldMsg () throws RemoteException; }
Create a Java class file using Listing 20.1, and save the file as HelloWorld.java
in your working
/src
directory.
In a real-world scenario, you could start by creating the remote interface to define the methods required for implementation in the Implementation
class. Alternatively, you could also define methods in the Implementation
class first and then declare them via the remote interface. Either way, the main objective is that they are identical.
The home interface acts as a factory for creating session bean instances and, therefore, exports the methods that provide life cycle services for the bean, such as creation and destruction of the bean. The home interface does not implement any business logic on behalf of the bean or possess any state.
The class that implements a session bean’s home interface within the EJB container is known as the session EJBHome
, which is generated at deployment. The EJBHome
class implements the methods of the javax.ejb.EJBHome
interface as well as the create<
METHOD
>
methods, which call a matching ejbCreate<
METHOD
>
method in the Implementation
class. The EJB container makes the session bean’s home interface available to a client through JNDI.
The following rules must be considered when creating a home interface for a session bean:
The home interface must extend the javax.ejb.EJBHome
interface.
Each create method must be named create<
METHOD
>
, and it must match one of the ejbCreate<
METHOD
>
methods defined in the SessionBean
class. The matching ejbCreate<
METHOD
>
method must have the same number and types of arguments. However, a stateless session bean’s home interface must define exactly one create()
method with no arguments that’s used to instantiate the bean.
The return type for a create<
METHOD
>
method must be the session bean’s remote interface.
The create<
METHOD
>
must throw the javax.ejb.CreateException
and java.rmi.RemoteException
exceptions.
The interface and methods must be declared public.
Listing 20.2 shows the home interface for the HelloWorld session bean.
Example 20.2. The Home Interface for the HelloWorld Session Bean
package examples; import java.rmi.*; import javax.ejb.*; /* Defines the methods for creating an instance of the HelloWorld session /* bean */ public interface HelloWorldHome extends EJBHome { /** * This create() method corresponds to the ejbCreate() method in the * Implementation class of the HelloWorld session bean. * The create() method returns the remote interface of the HelloWorld * session bean. */ public HelloWorld create() throws CreateException,RemoteException; }
Create a Java class file using Listing 20.2, and save the file as HelloWorldHome.java
in your working
/src
directory.
As a bean developer, you implement all business logic for a session bean within the Implementation
class, which is defined by the remote interface. All Implementation
classes must implement the javax.ejb.SessionBean
interface. The EJB container uses the setSessionContext()
method of the SessionBean
interface to associate a session bean instance with its context.
The following rules must be considered when creating the Implementation
class for a session bean:
The class must implement the javax.ejb.SessionBean
interface.
The class must be declared as public.
The class must have a public constructor that takes no parameters; this constructor is used to create the session bean instance.
The class must implement the business methods defined in the remote interface and the ejbCreate()
methods in the home interface.
Each business method must be defined as public.
The SessionBean
class is allowed to implement other methods (for example, helper methods called internally by business methods) in addition to methods the EJB specification requires.
If the class is a stateful session bean, it can optionally implement the javax.ejb.SessionSynchronization
interface.
The bean developer must implement all the following methods defined in the SessionBean
interface:
The ejbActivate()
and ejbPassivate()
methods must be implemented. For stateless session beans, the EJB container does not use these callback methods, so they can be left empty.
The ejbRemove()
method must be implemented.
The setSessionContext()
method must be implemented.
The following rules must be considered when creating ejbCreate()
methods for the Implementation
class:
The ejbCreate()
method must be implemented as it corresponds to the create()
method on the home interface.
The ejbCreate()
method must be declared as public.
The ejbCreate()
method must not be declared as final or static.
The ejbCreate()
method must return void.
The ejbCreate()
method can throw javax.ejb.EJBException
or javax.ejb.CreateException
exceptions.
Listing 20.3 shows the Implementation
class for the HelloWorld session bean.
Example 20.3. The Implementation
Class for the HelloWorld Session Bean
package examples; import javax.ejb.*; /** The Implementation class for the HelloWorld session bean */ public class HelloWorldBean implements SessionBean { /** * The session context is provided by the EJB container. A session bean must * retain its context. . */ private SessionContext ctx; /** An EJB must have a public, parameterless constructor */ public HelloWorldBean() {} /** Implement a simple logging mechanism to stdout */ private void log(String s) { if (true) System.out.println(s); } /** * This method is required by the EJB specification, * but is not used in this example. The container uses this method * to activate a stateful session bean after the bean has been * passivated using the ejbPassivate() method. */ public void ejbActivate() {} /** * This method is required by the EJB specification, * but is not used in this example. The container uses this method * to passivate an active stateful session bean. */ public void ejbPassivate() {} /** * This method is called by the EJB container to remove the * session bean from the EJB container. */ public void ejbRemove() { log("ejbRemove() called"); } /** Called by the EJB container to set the bean's session context. */ public void setSessionContext(SessionContext ctx) { log("setSessionContext called"); this.ctx = ctx; } /** * Called by the EJB container when a client calls the create() method in * the home interface. This method corresponds to the create() method * in the home interface of the HelloWorld session bean (HelloWorldHome.java). */ public void ejbCreate() throws CreateException { log("ejbCreate() called"); } public String getHelloWorldMsg () { log("Bean Method called"); return ("Stateless SessionBean says Hello World"); } }
Create a Java class file using Listing 20.3, and save the file as HelloWorldBean.java
in your working
/src
directory.
When you deploy your session bean, method calls to the bean are never handled directly by the remote or home interfaces. Instead, your remote method call to the bean is performed through the collaboration of two EJB container-generated classes called the stub and the skeleton for each interface you implement. Stubs are client-side objects, and skeletons are server-side objects. These classes are responsible for marshaling parameters and return values across the network connection, as shown in Figure 20.4.
The only restriction for remote methods is that all parameters and return values must be serializable.
A stub is basically a proxy of the remote object and has the same interface as the remote object. The stub is also located on the same machine as a calling client, which enables the client to use its methods in the same manner that it would use methods on the remote object directly. The stub is responsible for marshaling method calls into network messages to a target skeleton object.
Marshal means to serialize parameters so that they can be written to the remote object, which in turn deserializes them back into objects. Marshaling is built into the Java language through the Serializable
interface.
The skeleton is an object that deconstructs a network message into its method call. After deconstructing a message, the skeleton handles the logic for calling an equivalent method on the remote object that runs on the same machine as the skeleton.
The skeleton also takes the return value of the method call and converts it to a network message that can be sent back to the stub.
Because a session bean implements two interfaces (remote and home), all remote method calls to a session bean are handled through two sets of stubs and skeletons:
These stubs and skeletons are auto-generated and implemented by the EJB container when the session bean is deployed to WebLogic Server.
These home and remote stubs and skeletons work in concert to enable a client to remotely call a method on the session bean (see Figure 20.5).
The following list explains the numbered callouts in Figure 20.5:
During the startup of WebLogic Server, the home stub of every deployed bean is placed into the JNDI naming service. From here, a client can download the home stub to access a bean’s home interface.
The client uses the home stub to communicate with its home skeleton, which is controlled by the EJB container, to perform the following tasks:
Create a bean instance.
Provide state to the bean.
Associate a client context with the bean.
Create a remote skeleton and stub.
The home skeleton returns the remote stub specific to the client via its associated home stub.
After the client has obtained the remote stub, any operations called on the remote stub are communicated to the remote skeleton, which is then delegated to the bean in the container.
The primary difference between local and remote views of a bean is that a local view is optimized for accessing a bean by bypassing the need to use RMI for communicating with the bean. Because RMI is not used for communication, a local client accesses a session bean through the bean’s local interface or accesses an entity bean through the bean’s local home interface.
The container provides classes that implement the bean’s local and local home interfaces, as follows:
The class that implements a session bean’s local interface within the EJB container is known as the session EJBLocalObject
, which is generated at deployment. The EJBLocalObject
class implements the methods of the javax.ejb.EJBLocalObject
interface as well as business methods specific to the session bean. EJBLocalObject
is the local version of EJBObect
, which is used to delegate requests to the session bean.
The class that implements a session bean’s local home interface within the EJB container is known as the session EJBLocalHome
, which is generated at deployment. The EJBLocalHome
class implements the methods of the javax.ejb.EJBLocalHome
interface as well as the create<
METHOD
>
methods specific to the session bean. EJBLocalHome
is the local version of EJBHome
, which is used to manage the session bean’s life cycle.
Table 20.2 explores some additional differences between local and remote views to provide guidance on which view you should use to implement a session bean.
Table 20.2. Differences Between Local and Remote Views of Session Beans
The local and local home interfaces for the HelloWorld session bean are provided in Listings 20.4 and Listing 20.5.
Example 20.4. The Local Interface for the HelloWorld Session Bean
package examples; import javax.ejb.*; /** * This is the HelloWorld bean's local interface. */ public interface HelloWorldLocal extends EJBLocalObject { /** * This method is identical to the one defined in the remote interface of the * session bean, except this method does not throw a java.rmi.RemoteException. */ public String getHelloWorldMsg(); }
Example 20.5. The Local Home Interface for the HelloWorld Session Bean
package examples; import javax.ejb.*; /** * This is the local home interface for the HelloWorld bean. */ public interface HelloWorldLocalHome extends EJBLocalHome { /** * This create() method corresponds to the ejbCreate() method in the * Implementation class of the HelloWorld session bean. * The create() method returns the local interface.of the HelloWorld * session bean. As you can see, remote exceptions are not applicable for * local home interfaces. */ HelloWorldLocal create() throws CreateException; }
Unit testing your J2EE components after they’re deployed is always the best practice, and this simple session bean is no exception. Because the HelloWorld session bean has only one business method, getHelloWorldMsg()
, a simple Java client is required to test this method’s operation. Listing 20.6 shows the code for this Java client, and it has been fully commented to explain the processes of locating the home and remote interfaces and implementing the session bean’s method.
Example 20.6. The Test Java Client for the HelloWorld Session Bean
package examples; import java.rmi.*; import javax.rmi.PortableRemoteObject; import javax.naming.*; import java.util.*; /** * This class is an example of client code that calls * methods on a simple stateless session bean. */ public class HelloWorldClient { private static Context createJNDIContext() throws NamingException, RemoteException { Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory"); env.put(Context.PROVIDER_URL,"t3://localhost:7001"); Context context = new InitialContext( env ); return context; } /** * Main method to unit test the HelloWorld API */ public static void main(String[] args) { try { // use JNDI to look up the home interface for HelloWorld Context context = createJNDIContext(); // You could use the following statement to retrieve // the HelloWorld home /* HelloWorldHome home = (HelloWorldHome) context.lookup("examples.HelloWorldEJB"); * / // However, using javax.rmi.PortableRemoteObject // allows you to narrow the scope // to the home interface HelloWorldHome home = (HelloWorldHome ) PortableRemoteObject.narrow( context.lookup("examples.HelloWorldEJB"), examples.HelloWorldHome.class ) ; HelloWorld hello = home.create(); /* * The EJBObject will delegate the call to the HelloWorld * session bean, receive the result, and return it to this client. */ System.out.println(hello.getHelloWorldMsg()); /* * Remove the EJBObject. * The container will mark the EJBObject for destruction. */ hello.remove(); } catch( Exception err ) { System.err.println( err.toString() ); } } }
Two deployment descriptors are applicable to your session bean example:
The ejb-jar.xml
deployment descriptor file, which includes information on the session bean’s structure, internal dependencies, and application assembly information, per the J2EE specification.
The weblogic-ejb-jar.xml
deployment descriptor file, which includes specific information on the session bean’s behavior (such as concurrency, caching, clustering, and security) after it is deployed into WebLogic Server’s EJB container.
The weblogic-cmp-rdbms-jar.xml
file is applicable only if you are using Container-Managed Persistence.
The following sections describe these deployment descriptors in the context of the session bean example.
Listing 20.7 provides the ejb-jar.xml
deployment descriptor file for the HelloWorld session bean example.
Example 20.7. The ejb-jar.xml
File for the HelloWorld Session Bean Example
<!DOCTYPE ejb-jar PUBLIC '-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN' 'http://java.sun.com/dtd/ejb-jar_2_0.dtd'> <!-- Generated XML! --> <ejb-jar> <enterprise-beans> <session> <ejb-name>HelloWorldEJB</ejb-name> <home>examples.HelloWorldHome</home> <remote>examples.HelloWorld</remote> <local-home>examples.HelloWorldLocalHome</local-home> <local>examples.HelloWorldLocal</local> <ejb-class>examples.HelloWorldBean</ejb-class> <session-type>Stateless</session-type> <transaction-type>Container</transaction-type> </session> </enterprise-beans> <assembly-descriptor> <container-transaction> <method> <ejb-name>HelloWorldEJB</ejb-name> <method-name>*</method-name> </method> <trans-attribute>Required</trans-attribute> </container-transaction> </assembly-descriptor> </ejb-jar>
Table 20.3 describes the primary tag elements in Listing 20.7’s deployment descriptor that you should become familiar with.
Table 20.3. Tag Elements in the ejb-jar.xml
File for the Session Bean Example
Element | Description |
---|---|
| Specifies a unique name for the EJB, used to identify the bean in deployment descriptors. |
| Specifies the fully qualified name of the home interface. |
| Specifies the fully qualified name of the remote interface. |
| Specifies the fully qualified name of the local home interface. |
| Specifies the fully qualified name of the local interface. |
| Specifies the fully qualified name of the EJB class. |
| Specifies the type of session bean—stateless or stateful. |
Create your ejb-jar.xml
file using Listing 20.7, and save the file in your working
/deployment
directory.
Listing 20.8 provides the weblogic-ejb-jar.xml
deployment descriptor file for the HelloWorld session bean example.
Example 20.8. The weblogic-ejb-jar.xml
File for the HelloWorld Session Bean Example
<!DOCTYPE weblogic-ejb-jar PUBLIC '-//BEA Systems, Inc.//DTD WebLogic 7.0.0 EJB//EN' 'http://www.bea.com/servers/wls700/dtd/weblogic-ejb-jar.dtd'> <!-- Generated XML! --> <weblogic-ejb-jar> <weblogic-enterprise-bean> <ejb-name>HelloWorldEJB</ejb-name> <stateless-session-descriptor> <pool> <initial-beans-in-free-pool>5</initial-beans-in-free-pool> </pool> <stateless-clustering> <home-is-clusterable>False</home-is-clusterable> <stateless-bean-is-clusterable>False</stateless-bean-is-clusterable> <stateless-bean-load-algorithm>RoundRobin</stateless-bean-load-algorithm> </stateless-clustering> </stateless-session-descriptor> <transaction-descriptor> </transaction-descriptor> <enable-call-by-reference>True</enable-call-by-reference> <jndi-name>examples.HelloWorldEJB</jndi-name> <local-jndi-name>examples.HelloWorldEJBLocal</local-jndi-name> </weblogic-enterprise-bean> </weblogic-ejb-jar>
Table 20.4 describes the primary tag elements in Listing 20.8’s deployment descriptor that you should become familiar with.
Table 20.4. Tag Elements in the weblogic-ejb-jar.xml
File for the Session Bean Example
Create your weblogic-ejb-jar.xml
file from Listing 20.8 using a text editor or an XML editor, and save the file in your working
/deployment
directory. You can also use WebLogic Builder to create and validate your deployment descriptors.
Now that you have created your HelloWorld session bean class files and deployment descriptors, the next step is to build your deployment unit (JAR file), which requires you to do the following:
Compile the EJB classes by using the javac
compiler from the command line.
Add the deployment descriptor files to the compiled unit by using the jar
utility to create a temporary archive file.
Generate a deployment unit (JAR) that includes the following:
The container’s classes, which are internal WebLogic Server–specific class files that WebLogic Server uses to access the bean.
The implementation of the home, remote, and local interfaces.
This task is performed with the weblogic.ejbc
utility, which generates container classes and implementation classes by inspecting the bean’s Implementation
class file and remote and home interfaces and by examining the session bean’s deployment descriptors (see Figure 20.6).
To perform these tasks, it is a good practice to create a build/make script that can automate the whole build process for you. The build script (build.cmd
) for compiling, packaging, and generating the container classes is shown in Listing 20.9.
Example 20.9. An Example of a Build Script
@rem ******************************************************* @rem Cleaning working area @rem ******************************************************* echo y | rmdir /s classes echo y | rmdir /s lib mkdir classes mkdir lib @rem ******************************************************* @rem Compiling the session bean files @rem ******************************************************* javac -d classes src*.java @rem ******************************************************* @rem Copy deployment descriptors into the META-INF directory @rem ******************************************************* mkdir classesMETA-INF copy deployment*.xml classesMETA-INF @rem ******************************************************* @rem Create the temporary .jar file @rem ******************************************************* cd classes jar cf ..lib emp.jar * cd .. @rem ******************************************************* @rem Generating the container classes and creating the deployment @rem unit @rem ******************************************************* cd lib java weblogic.ejbc -keepgenerated temp.jar HelloWorld.jar del temp.jar cd ..
You can use two techniques to deploy your HelloWorld session bean. The easiest is simply copying the HelloWorld.jar
file into the applications
directory within your WebLogic Server domain directory. If your WebLogic Server is started in development mode, which is the default, WebLogic Server auto-deploys the JAR file.
The other deployment technique is a more formal procedure using WebLogic Builder or the Administration Console. Follow these steps to deploy your HelloWorld.jar
file to WebLogic Server using the Administration Console:
Launch and log in to the Administration Console.
Expand the Deployments node in the left pane.
Right-click the EJB node and click the Configure a New EJB option.
Locate the HelloWorld.jar
archive on your file system using the Administration Console’s directory navigation mechanism.
Click [select]
to the left of the HelloWorld.jar
file.
Select a target server from the Available Servers list box.
Enter a name for the session bean application, such as HelloWorld
, to identify it in the Administration Console.
Click Configure and Deploy. The Administration Console displays the Deploy tab, which lists deployment status and activities.
After your session bean has been deployed to WebLogic Server, the EJB container creates five instances of the bean in the free pool, as specified by the <initial-beans-in-free-pool>
element in weblogic-ejb-jar.xml
. Because logging was enabled in each method of the HelloWorld bean (see Listing 20.6), the methods called to instantiate the bean into the free pool are displayed in WebLogic Server’s stdout
.
To test your HelloWorld session bean, follow these steps:
Open a command-prompt window and set your Java environment.
Set the CLASSPATH
to include the location of the HelloWorld.jar
file, as shown in this statement:
Set CLASSPATH=HelloWorld.jar;%CLASSPATH%
Run the application using the following command, as shown in Figure 20.7:
java examples.HelloWorldClient
The WebLogic EJB container completely manages the life cycle of a stateless session bean. As shown in Figure 20.8, a stateless session bean can exist in three states.
The legal life cycle operations permitted on stateless session beans’ methods are summarized in Table 20.5 and discussed in the following sections.
Table 20.5. Legal Operations for Stateless Session Bean Methods
In the Does Not Exist state, a stateless session bean literally does not exist and has not been instantiated. Also, the stateless bean has no identity. For example, by default, no stateless bean instance exists in WebLogic Server during its boot process.
If the container decides to instantiate a stateless session bean, it does the following:
Calls the newInstance()
method on the stateless bean class to create a new instance. The EJB container can perform instance creation at any time because there is no direct relationship between a client’s call of the create()
method and the creation of a bean instance.
Calls the setSessionContext()
method on the new bean instance, passing a SessionContext
object as the parameter. The session bean uses this object to communicate with the EJB container.
Calls the ejbCreate()
method on the new bean instance to initialize the bean.
The stateless session bean instance is now in the Method Ready Pool state, ready for any client to delegate a method call. While the bean is in this state, it exists within the EJB container’s free pool, which is a repository for stateless beans instantiated by the EJB container. The free pool stores unbound stateless beans that are not active and are processing a method call. WebLogic Server uses the free pool to improve performance and throughput for stateless beans, including message-driven beans.
When WebLogic Server starts, if stateless session beans have been deployed to the server, the WebLogic EJB container automatically instantiates multiple instances of the beans, as specified by the value of the <initial-beans-in-free-pool>
element in weblogic-ejb-jar.xml
. These bean instances are placed in the free pool, ready to service incoming remote method calls. Populating the free pool in this manner improves the initial response time for activating a stateless bean instance because initial requests for the bean can be satisfied without generating a new bean instance.
<initial-beans-in-free-pool>
defaults to 0 if the element is not defined, which implies that WebLogic Server does not prepopulate the free pool with any stateless bean instances.
The EJB container creates new instances of stateless beans as needed for concurrent and parallel method processing. However, the maximum number of stateless session bean instances that can be accommodated in the free pool depends on two factors:
The value of the <max-beans-in-free-pool>
element in weblogic-ejb-jar.xml
, which places an upper boundary on the number of stateless bean instances the container creates. An upper boundary might be set when a stateless session bean models a session facade, limiting the number of connections to the back-end server components.
The number of execution threads available in WebLogic Server to process each remote method call.
Typically, the EJB container no longer needs the bean instance when it needs to reduce the number of stateless bean instances in the method-ready pool. When this happens, the container calls ejbRemove()
on the bean, which transitions the bean to the Does Not Exist state. Also, if a RuntimeException
occurs within a stateless session bean’s life cycle, the bean instance transitions to the Does Not Exist state. This does not affect the client because the EJB container delegates another bean instance from the pool to service the client.
When a client calls a create()
method on the home interface, the container does not necessarily create an instance of the bean. It just returns a remote interface. Only when method calls are made against a bean’s remote interface does the container find a stateless bean instance in the free pool or create an instance to delegate the method call. The stateless bean then remains active throughout the duration of the client’s method call. When that call is completed, the EJB container detaches the bean instance from the client and returns the bean instance to the container’s free pool.
A container serializes calls to each session bean instance. For this reason, if incoming method requests surpass the number of stateless beans, the method requests must wait until the EJB container can create additional stateless bean instances or the active beans have been unbound from their clients and placed back in the free pool.
Because stateful session beans are bound to a specific client and maintain conversational state, WebLogic Server cannot use a free pool mechanism to keep method-ready stateful beans available. Instead, WebLogic Server uses a cache that stores active EJB instances in memory so that they are immediately available to service their client’s method calls.
However, stateful session beans consume memory resources. For this reason, special provisions are required to ensure that fixed memory resources allocated to WebLogic Server do not become constrained by an increasing number of clients calling methods on stateful beans. To accommodate a large stateful session bean client base, WebLogic Server’s EJB container swaps the unused stateful bean instances out to virtual memory by using Java object serialization. This process, known as passivation, conserves memory resources by limiting the number of stateful bean instances that can be in memory at any given time. When a client calls a remote method on a stateful session bean’s remote interface, and the bean instance is discovered to be passivated, the EJB container loads the bean instance back into memory by deserializing the bean instance object. This process is known as activation. Both concepts are critical in understanding a stateful session bean’s life cycle.
As shown in Figure 20.9, a stateful session bean can exist in three states.
The legal life cycle operations permitted on stateful session beans’ methods are summarized in Table 20.6 and discussed in the following sections.
Table 20.6. Legal Operations on Stateful Session Bean Methods
As clients look up and obtain references to individual beans by calling Create<
Method
>
on the home stub, WebLogic Server initializes the new stateful bean instances by calling newInstance()
, setSessionContext()
, and, finally, ejbCreate()
on the bean, returning the EJBobject
reference to the client. After the bean is created, it is immediately considered to be in a Method Ready state and placed in the cache. Hence, the number of stateful beans that can exist in a Method Ready state is client driven, not controlled by the EJB container. In the Method Ready state, the stateful bean instance serves its client’s method calls and remains in this state until one of the following occurs:
The client calls the ejbRemove()
method on the stateful bean, at which point the bean transitions to the Does Not Exist state.
The container passivates the bean, at which point the bean transitions to the Passivated state. Passivation uses the Not Recently Used (NRU) algorithm by default, which passivates any recently unused stateful beans.
The stateful bean is timed out of cache by the container, at which point the stateful bean is in the Does Not Exist state. A WebLogic administrator can specify the amount of time a stateful bean exists before it’s destroyed.
Immediately before passivation, the EJB container calls the ejbPassivate()
method on the stateful bean, which allows the developer to provide code to deallocate open resources, such as JDBC connections, gracefully. The container passivates the bean only after the ejbPassivate()
method has been called.
The resources and information that can be preserved for a stateful bean in a Passivated state include the following:
JNDI Environmental Naming Context
References to the session context
References to other beans’ home interfaces
References to other beans’ remote interfaces
The JTA UserTransaction
type
Primitive data types and serializable objects
The EJB container activates a stateful bean by calling the bean’s ejbActive()
method. The bean developer can add code in this method to allocate resources that were closed during passivation and to initialize transient attributes to the proper values.
Only the WebLogic EJB container can transition a stateful bean into the Passivated state. Therefore, to maintain continuous high performance, WebLogic Server reserves the cache for active and recently used stateful session beans. When a stateful bean no longer meets this criteria, it becomes eligible for passivation. This does not imply that a bean meeting this criteria will be passivated; the EJB container takes other factors, such as constraints on server resources, into consideration before a stateful bean is passivated. However, you can influence passivation of stateful session beans through the weblogic-ejb-jar.xml
deployment descriptor elements described in the following sections.
<max-bean-in-cache>
This element specifies the maximum number of stateful beans of a specific class that are allowed in memory. When <max-bean-in-cache>
is reached, WebLogic Server begins to passivate some beans that have not been recently used (Least Recently Used [LRU]) by the client. The default value of <max-beans-in-cache>
is 100
. If <max-beans-in-cache>
is reached and all EJBs in the cache are being used by clients, WebLogic Server throws a CacheFullException
.
When analyzing ways to increase performance through the <max-bean-in-cache>
element, you should analyze the operation of your stateful bean application and include answers to the following questions:
How does the stateful bean application relate to the JVM heap size?
What is the total number of beans being deployed?
What types of EJBs are being deployed: session, message-driven, or entity beans?
What is the memory footprint for deployed beans?
What is the expected client request load?
Based on these statistics, you can reach a suitable value for the <max-beans-in-cache>
element. Ideally, the setting you select should not exceed the available JVM heap memory or bring WebLogic Server to a halt by competing for memory.
<idle-timeout-seconds>
This element defines the maximum length of time a stateful bean should remain in the cache, after which WebLogic Server can remove the bean instance if the number of beans in the cache approaches the limit of <max-beans-in-cache>
.
You can specify explicit passivation of stateful EJBs that have reached <idle-timeout-seconds>
by setting the <cache-type>
element in the weblogic-ejb-jar.xml
file, which specifies the order in which stateful beans are removed from the cache. This setting has two values—Least Recently Used (LRU) and Not Recently Used (NRU):
If you specify LRU, the container passivates the bean when <idle-timeout-seconds>
is reached.
If you specify NRU, the container passivates the bean when there is pressure in the cache.
<idle-timeout-seconds>
determines how often the container checks to see how full the cache is. The default is 600
.
After a stateful session bean instance is passivated, a client must use the EJB instance before <idle-timeout-seconds>
is reached. Otherwise, WebLogic Server removes the passivated instance from disk (Does Not Exist state).
In this section, you leverage the skills you have already learned by developing the HelloWorld stateless session bean, but this time you develop a stateful session bean that you influence to go through its life cycle states.
The stateful session bean you’re developing is named “Passivation” and consists of the following class files:
examples.Passivation
(remote interface)
examples.PassivationHome
(home interface)
examples.PassivationBean
(Implementation
class)
You’ll also create examples.PassivationClient
, the test client class file.
The following list describes how you influence this stateful bean to transition through its life cycle states:
The test client will create multiple instances (50, for instance) of the Passivation stateful session bean.
Each instance of the stateful bean maintains a conversation with the client by incrementing a simple counter and returning the value to the client thread.
You cause an instance of the stateful bean to be idle for a while by sleeping the client thread for a short period.
You modify the <idle-timeout-seconds>
and <max-beans-in-cache>
elements in the weblogic-ejb-jar.xml
file to cause the EJB container to passivate and activate the stateful bean instances.
To develop this example, follow these steps:
Set up a new working directory and subdirectory structure, using the same structure as the earlier HelloWorld example.
Create the following class files and save them into the working
/src
directory:
Use Listing 20.10 to create the home interface for a stateful bean.
Use Listing 20.11 to create the remote interface for the stateful bean.
Use Listing 20.12 to create the Implementation
class for the stateful bean.
Example 20.12. The Implementation
Class for the Passivation Stateful Bean
package examples; import javax.ejb.*; public class PassivationBean implements SessionBean { // The current counter will be the conversational state. public int val; public int count() { System.out.println("count()"); return ++val; } public void ejbCreate(int val) throws CreateException { this.val = val; System.out.println("ejbCreate()"); } public void ejbRemove() { System.out.println("ejbRemove()"); } public void ejbActivate() { System.out.println("ejbActivate()"); } public void ejbPassivate() { System.out.println("ejbPassivate()"); } public void setSessionContext(SessionContext ctx) { } }
Use Listing 20.13 to create the test client for the stateful bean.
Example 20.13. The Test Client for the Passivation Stateful Bean
package examples; import java.rmi.*; import javax.rmi.PortableRemoteObject; import javax.naming.*; import java.util.*; public class PassivationClient { private static Context createJNDIContext() throws NamingException, RemoteException { Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory"); env.put(Context.PROVIDER_URL,"t3://localhost:7001"); Context context = new InitialContext( env ); return context; } public static void main(String[] args) { try { // use JNDI to look up the home interface for HelloWorld Context context = createJNDIContext(); PassivationHome home = (PassivationHome ) PortableRemoteObject.narrow( context.lookup("examples.PassivationEJB"), examples.PassivationHome.class ); /* * An array to hold 50 count EJB objects */ Passivation count[] = new Passivation[50]; int countVal = 0; /* * Create and count() on each member of the array */ System.out.println("Instantiating Stateful Beans..."); for (int i=0; i < 50; i++) { /* * Create an EJBObject and initialize * it to the current count value. */ count[i] = home.create(countVal); countVal = count[i].count(); System.out.println(countVal); /* * Sleep for 1 second */ Thread.sleep(1000); } /* * Call count() on each EJB object to * ensure the beans are activated if in a passivated state */ System.out.println("Calling count() on beans..."); for (int i=0; i < 50; i++) { /* * Add 1 and print */ countVal = count[i].count(); System.out.println(countVal); /* * Sleep for 1 second */ Thread.sleep(1000) ; } /* * Remove objects */ for (int i=0; i < 50; i++) { count[i].remove(); } } catch (Exception e) { e.printStackTrace(); } } }
Use Listing 20.14 to create the ejb-jar.xml
deployment descriptor and save it in the working
/deployment
directory.
Example 20.14. The ejb-jar.xml
Deployment Descriptor for the Passivation Stateful Bean
<!DOCTYPE ejb-jar PUBLIC '-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN' 'http://java.sun.com/dtd/ejb-jar_2_0.dtd'> <!-- Generated XML! --> <ejb-jar> <enterprise-beans> <session> <ejb-name>Passivation</ejb-name> <home>examples.PassivationHome</home> <remote>examples.Passivation</remote> <ejb-class>examples.PassivationBean</ejb-class> <session-type>Stateful</session-type> <transaction-type>Container</transaction-type> </session> </enterprise-beans> </ejb-jar>
What differentiates a stateless and stateful session bean at deployment is how the bean is defined in the weblogic-ejb-jar.xml
deployment descriptor using the <session-type>
element.
Use Listing 20.15 to create the weblogic-ejb-jar.xml
deployment descriptor and save it in the working
/deployment
directory.
Example 20.15. The weblogic-ejb-jar.xml
Deployment Descriptor for the Passivation Stateful Bean
<!DOCTYPE weblogic-ejb-jar PUBLIC '-//BEA Systems, Inc.//DTD WebLogic 7.0.0 EJB//EN' 'http://www.bea.com/servers/wls700/dtd/weblogic-ejb-jar.dtd'> <!-- Generated XML! --> <weblogic-ejb-jar> <weblogic-enterprise-bean> <ejb-name>Passivation</ejb-name> <stateful-session-descriptor> <stateful-session-cache> <max-beans-in-cache>45</max-beans-in-cache> <idle-timeout-seconds>500</idle-timeout-seconds> <cache-type>LRU</cache-type> </stateful-session-cache> <stateful-session-clustering> </stateful-session-clustering> </stateful-session-descriptor> <transaction-descriptor> </transaction-descriptor> <jndi-name>examples.PassivationEJB</jndi-name> </weblogic-enterprise-bean> </weblogic-ejb-jar>
The elements of the weblogic-ejb-jar.xml
deployment descriptor file that can influence passivation of a stateful session bean are highlighted in Listing 20.15. You can modify these values, however, for the initial test; use the specified values.
Compile and build the Passivation.jar
deployment unit using a build script (provided in Listing 20.6).
Deploy the stateful bean to an active WebLogic server by copying the Passivation.jar
file into your WebLogic domain’s applications
directory.
To test your Passivation stateful session bean, follow these steps:
Open a command-prompt window and set your Java environment.
Set the CLASSPATH
to include the location of the Passivation.jar
file, as shown in this statement:
Set CLASSPATH=Passivation.jar;%CLASSPATH%
Run the application using the following command, as shown in Figure 20.10:
java examples.PassivationClient
As shown in Figure 20.10, the EJB container is passivating and activating the stateful bean. You can also use the Administration Console to monitor the activity and status of your deployed stateful session beans (see Figure 20.11).
The WebLogic EJB container provides both Container-Managed and Bean-Managed Transaction support for session beans, which is specified by the <transaction-type>
element in the bean’s ejb-jar.xml
deployment descriptor. This tag can have the value Bean
or Container
. Bean
implies that the EJB will perform all the transaction management, and Container
means that the bean requests the WebLogic EJB container to perform transaction management. The following sections discuss both transaction management techniques.
▸ For a detailed discussion on the Java Transaction API, see Chapter 16, “Managing Java Transactions Using JTA,” p. 527.
When Container-Managed Transactions (CMT) are used, the EJB container requires additional information on how and when to start transactions. This information is also provided in the deployment descriptor in the <container-transaction>
element. Six keywords define the transaction attribute (see Table 20.7). The transaction attribute can be applied on a per-bean basis or to individual methods within the bean.
Table 20.7. Transaction Attributes for Session Beans
If no <container-transaction>
element is provided in the deployment descriptor, the WebLogic EJB container defaults to Supports
for all methods in the EJB. An example of the <container-transaction>
element from the ejb-jar.xml
file is shown in Listing 20.16.
Listing 20.16 sets the Required
transaction attribute for all methods in the MySessionBean bean.
The <method>
tag section can have specific method names. To support method overloading, a list of method parameters can be supplied to select a specific method signature. An example of a <container-transaction>
element that specifies the Mandatory
transaction attribute for the getBalance( String account )
method is shown in Listing 20.17.
Bean-Managed Transactions (BMT) are indicated when the <transaction-type>
element in the deployment descriptor is set to Bean
. The EJB must then directly call methods on the UserTransaction
object. With CMT, transaction boundaries are set by the client or EJB container. With BMT, the EJB gets a reference to the UserTransaction
object by calling getUserTransaction()
on the SessionContext
object. The SessionContext
object is passed to the EJB through the setSessionContext()
method. The EJB can call the begin, commit, and rollback methods on the UserTransaction
object. A stateless session bean must commit or roll back every transaction before returning from the method call. A stateful session bean can keep a transaction active across multiple method calls.
Keep in mind that although the stateful session bean is caching the client’s conversational state, the state is not considered transactional. Therefore, it is not automatically rolled back to some initial state when the transaction it participates in is rolled back. The bean developer needs to provide logic to accomplish this task.
Session beans are an important component of the J2EE specification, giving you the ability to develop typically client-side business logic within the realm of the EJB container. This chapter has introduced you to the types of session beans you can develop and described their life cycles and differences. You have had the opportunity for hands-on experience in developing stateless and stateful session beans to get you comfortable with the technology.
To continue the discussion of session beans in the context of a WebLogic cluster, read Chapter 25, “Implementing Highly Available and Scalable Solutions Using the WebLogic Cluster.”