BEA Home | Events | Solutions | Partners | Products | Services | Download | Developer Center | WebSUPPORT
| WebLogic Server Doc Home | Programming WebLogic EJB | Previous Topic | Next Topic | Contents | View as PDF

The WebLogic Server EJB Container and Supported Services

The following sections describe the WebLogic Server EJB container, various aspects of EJB behavior in terms of the features and services that the container provides. See to WebLogic Server Container-Managed Persistence Services, for more information on container-managed persistence (CMP).

- EJB Container

- EJB Life Cycle

- Comparing the Performance of Stateless Session Beans to BMP EJBs

- ejbLoad() and ejbStore() Behavior for Entity EJBs

- Setting Entity EJBs to Read-Only

- EJBs in WebLogic Server Clusters

- Transaction Management

- Resource Factories

- Locking Services for Entity EJBs

EJB Container

The EJB container is a runtime container for the deployed EJBs that is automatically created when WebLogic Server is started. During the entire life cycle of the entity object, from its creations to removal, it lives in the container. The EJB container provides a standard set of services, including caching, concurrency, persistence, security, transaction management, locking, environment, memory replication, environment, and clustering for the entity objects that live in the container.

You can deploy multiple entity beans in a single container. For each entity bean deployed in a container, the container provides a home interface. The home interface allows a client to create, find, and remove entity objects that belong to the entity bean as well as execute home business methods which are not specific to a particular entity bean object. A client can look up the entity bean's home interface through JNDI. The container is responsible for making the entity bean's home interface available in the JNDI name space. For instructions on looking up the home interface through JNDI, see Programming WebLogic JNDI.

EJB Life Cycle

The following sections provide information about how the container supports caching services. They describe the life cycle of EJB instances in WebLogic Server, from the perspective of the server. These sections use the term EJB instance to refer to the actual instance of the EJB class. EJB instance does not refer to the logical instance of the EJB as seen from the point of view of a client.

Entity EJB Life Cycle

WebLogic Server provides these features to improve performance and throughput for entity EJBs.

- Free pool—stores anonymous entity beans that are used for invoking finders, home methods, and creating entity beans.

- Cache—contains instances that have an identity—a primary key, or are currently enlisted in a transaction (READY and ACTIVE entity EJB instances).

The sections that follow describe the life cycle of an entity bean instance, and how the container populates and manages the free pool and cache. For an illustration of life cycle transitions, see Figure 4-1.

Initializing Entity EJB Instances (Free Pool)

If you specify a non-zero value for initial-beans-in-free-pool, WebLogic Server populates the pool with the specified quantity of bean instances at startup.

The default value of initial-beans-in-free-pool is zero. Populating the free pool at startup improves initial response time for the EJB, because initial requests for the bean can be satisfied without generating a new instance.

An attempt to obtain an entity bean instance from the free pool will always succeed, even if the pool is empty. If the pool is empty, a new bean instance is created and returned.

POOLED beans are anonymous instances, and are used for finders and home methods. The maximum number of instances the pool can contain is specified by the value of the max-beans-in-free-pool element in weblogic-ejb-jar.xml.

READY and ACTIVE Entity EJB Instances (Cache)

When a business method is called on a bean, the container obtains an instance from the pool, calls ejbActivate, and the instance services the method call.

A READY instance is in the cache, has an identity—an associated primary key—but is not currently enlisted in a transaction. WebLogic maintains READY entity EJB instances in least-recently-used (LRU) order.

An ACTIVE instance is currently enlisted in a transaction. After completing the transaction, the instance becomes READY, and remains in cache until space is needed for other beans.

The Current Beans in Cache field in the monitoring tab of the Administration Console displays the count of READY and ACTIVE beans.

The effect of max-beans-in-cache, and the quantity of instances with the same primary key allowed in the cache vary by concurrency strategy, as described in the following section, Cache Rules Vary by Concurrency Strategy.

Cache Rules Vary by Concurrency Strategy

Table 4-1 lists, for each concurrency strategy:

- How the value of the max-beans-in-cache element in weblogic-ejb-jar.xml limits the number of entity bean instances in the cache.

- How many entity bean instances with the same primary key are allowed in the cache.

  Table 4-1 Entity EJB Caching Behavior by Concurrency Type

  Concurrency Option | What is the effect of max-beans-in-cache on the number of bean instances in the cache? | How many instances with same primary key can exist in cache simultaneously?
  --- | --- | ---
  Exclusive | max-beans-in-cache = number of ACTIVE bean + number of READY instances. | one
  Database | The cache can contain up to max-beans-in-cache ACTIVE bean instances and up to max-beans-in-cache READY bean instances. | multiple
  ReadOnly | max-beans-in-cache = number of ACTIVE bean + number of READY instances. | one

Removing Beans from Cache

READY entity EJB instances are removed from the cache when the space is needed for other beans. When a READY instance is removed from cache, ejbPassivate is called on the bean, and the container will try to put it back into the free pool.

When the container tries to return an instance to the free pool and the pool already contains max-beans-in-free-pool instances, the instance is discarded.

ACTIVE entity EJB instances will not be removed from cache until the transaction they are participating in commits or rolls back, at which point they will become READY, and hence eligible for removal from the cache.

Entity EJB Life Cycle Transitions

Figure 4-1 illustrates the Entity EJB free pool and cache, and the transitions that occur throughout an instance's life cycle.

Figure 4-1 Entity Bean Life Cycle

Stateless Session EJB Life Cycle

WebLogic Server uses a free pool to improve performance and throughput for stateless session and message-driven EJBs. The free pool stores unbound stateless session EJBs. Unbound EJBs are instances of a stateless session EJB class that are not processing a method call.

The following figure illustrates the WebLogic Server free pool, and the processes by which stateless EJBs enter and leave the pool. Dotted lines indicate the state of the EJB from the perspective of WebLogic Server.

Figure 4-2 WebLogic Server free pool showing stateless session EJB life cycle

Initializing Stateless Session EJB Instances

By default, no stateless session EJB instances exist in WebLogic Server at startup time. As clients access individual beans, WebLogic Server initializes new instances of the EJB class.

To configure WebLogic Server to populate the free pool with inactive EJB instances EJB at startup, specify the desired quantity in the initial-beans-in-free-pool deployment element, in the stateful-session-descriptor stanza of weblogic-ejb-jar.xml. This can improve initial response time when clients access EJBs, because initial client requests can be satisfied by activating the bean from the free pool (rather than initializing the bean and then activating it). By default, initial-beans-in-free-pool is set to 0.

Note: The maximum size of the free pool is limited by available memory, the number of execute threads, or the value of the max-beans-in-free-pool deployment element.

Activating and Pooling Stateless Session EJBs

When a client calls a method on a stateless EJB, WebLogic Server obtains an instance from the free pool, or initializing and activating a new instance, if necessary. The EJB remains active for the duration of the client's method call. After the method completes, the EJB instance is returned to the free pool. Because WebLogic Server unbinds stateless session beans from clients after each method call, the actual bean class instance that a client uses may be different from invocation to invocation.

If all instances of an EJB class are active and max-beans-in-free-pool has been reached, new clients requesting the EJB class will be blocked until an active EJB completes a method call. If the transaction times out (or, for non-transactional calls, if five minutes elapse), WebLogic Server throws a RemoteException.

Stateful Session EJB Life Cycle

WebLogic Server uses a cache of bean instances to improve the performance of stateful session EJBs. The cache stores active EJB instances in memory so that they are immediately available for client requests. The cache contains EJBs that are currently in use by a client and instances that were recently in use. Stateful session beans in cache are bound to a particular client.

The following figure illustrates the WebLogic Server cache, and the processes by which stateful EJBs enter and leave the cache.

Figure 4-3 Stateful Session EJB Life Cycle

Stateful Session EJB Creation

No stateful session EJB instances exist in WebLogic Server at startup. Before a client begins accessing a stateful session bean, it creates a new bean instance to use during its session with the bean. When the session is over the instance is destroyed. While the session is in progress, the instance is cached in memory.

Stateful Session EJB Passivation

Passivation is the process by which WebLogic Server removes an EJB instance from cache while preserving its state on disk. While passivated, EJBs are not in memory and are not immediately available for client requests, as they are when in the cache.

The EJB developer must ensure that a call to the ejbPassivate() method leaves a stateful session bean in a condition where WebLogic Server can serialize its data and passivate the bean's instance. During passivation, WebLogic Server attempts to serialize any fields that are not declared transient. This means that you must ensure that all non-transient fields represent serializable objects, such as the bean's remote or home interface. EJB 2.1 specifies the field types that are allowed.

The rules that govern the passivation of stateful session beans vary, based on the value of the beans cache-type element, which can be:

- LRU—least recently used, referred to as eager passivation.

- NRU—not recently used, referred to as lazy passivation

The idle-timeout-seconds and max-beans-in-cache elements also affect passivation and removal behaviors, based on the value of cache-type.

Eager Passivation (LRU)

When you configure eager passivation for a stateful session bean by setting cache-type to LRU, the container:

- Passivates instances to disk:

  - as soon as an instance has been inactive for idle-timeout-seconds, regardless of the value of max-beans-in-cache.

  - when max-beans-in-cache is reached, even though idle-timeout-seconds has not expired.

- Removes a passivated instance from disk after it has been inactive for idle-timeout-seconds after passivation. This is referred to as a lazy remove.

Lazy Passivation (NRU)

When lazy passivation is configured by setting cache-type to NRU, the container avoids passivating beans, because of the associated systems overhead—pressure on the cache is the only event that causes passivation or eager removal of beans. The container:

- Removes a bean instance from cache when idle-timeout-seconds expires, and does not passivate it to disk. This is referred to as a eager remove. An eager remove ensures that an inactive instance does not consume memory or disk resources.

- Passivates instances to disk when max-beans-in-cache is reached, even though idle-timeout-seconds has not expired.

Managing EJB Cache Size

For a discussion of managing cache size to optimize performance in a production environment see "Setting EJB Cache Size" in WebLogic Server Performance and Tuning.

Specifying the Persistent Store Directory for Passivated Beans

When a stateful session bean is passivated, its state is stored in a file system directory known as the persistent store directory. The persistent store directory contains one subdirectory for each passivated bean.

The persistent store directory is created by default in the root directory of your WebLogic Server installation, for example:

D:\releases\610\pstore\

The path to the persistence store is:

WLHOME\persistent-store-dir

where:

- WLHOME—the directory where WebLogic Server is installed, for example:

  D:\releases\610\

- persistent-store-dir—the value of the of the persistent-store-dir element in the <stateful-session-descriptor> stanza of weblogic-ejb-jar.xml. If no value is specified for persistent-store-dir, the directory is named pstore by default.

The persistent store directory contains a subdirectory for each passivated bean. The subdirectory name is comprised of the bean's home and JNDI name. For example:

D:\releases\610\pstore\statefulSessionful.TraderHome

Concurrent Access to Stateful Session Beans

In accordance with the EJB 2.0 specification, simultaneous access to a stateful session EJB results in a RemoteException. This access restriction on stateful session EJBs applies whether the EJB client is remote or internal to WebLogic Server. To override this restriction and configure a stateful session bean to allow concurrent calls, set the allow-concurrent-calls deployment element.

If multiple servlet classes access a stateful session EJB, each servlet thread (rather than each instance of the servlet class) must have its own session EJB instance. To prevent concurrent access, a JSP/servlet can use a stateful session bean in request scope.

Comparing the Performance of Stateless Session Beans to BMP EJBs

To improve performance, we recommend that you use stateless session beans or CMP (container-managed persistent) entity beans instead of BMP (bean-managed persistent) entity beans for retrieving data. Tests have shown that because BMP entity beans can not cache data during a finder query, the performance of stateless session beans may be as much as 90 percent greater than BMP entity beans. For example, a BMP entity bean that returns 100 beans from a finder query does one JDBC call to create bean references when the finder query is run and then one JDBC call per bean, to load each bean as each is accesses by the client. This means that the finder query for the BMP entity bean does a total of 101 calls to the database. By comparison, the stateless session bean does just one JDBC call, so it's performance is much faster.

The fact that BMP entity beans do not scale very well is a known performance limitation.

In addition, CMP entity beans can cache data during a finder query. So as with the stateless session bean, only one query is performed.

ejbLoad() and ejbStore() Behavior for Entity EJBs

WebLogic Server reads and writes the persistent fields of entity EJBs using calls to ejbLoad() and ejbStore(). By default, WebLogic Server calls ejbLoad() and ejbStore() in the following manner:

1. A transaction is initiated for the entity EJB. The client may explicitly initiate a new transaction and invoke the bean, or WebLogic Server may initiate a new transaction in accordance with the bean's method transaction attributes.

2. WebLogic Server calls ejbLoad() to read the most current version of the bean's persistent data from the underlying datastore.

3. When the transaction commits, WebLogic Server calls ejbStore() to write persistent fields back to the underlying datastore.

This simple process of calling ejbLoad() and ejbStore() ensures that new transactions always use the latest version of the EJB's persistent data, and always write the data back to the datastore upon committing. In certain circumstances, however, you may want to limit calls to ejbLoad() and ejbStore() for performance reasons. Alternately, you may want to call ejbStore() more frequently to view the intermediate results of uncommitted transactions.

WebLogic Server provides several deployment descriptor elements in the weblogic-ejb-jar.xml and weblogic cmp-rdbms-jar.xml files that enable you to configure ejbLoad() and ejbStore() behavior.

Using db-is-shared to Limit Calls to ejbLoad()

WebLogic Server's default behavior of calling ejbLoad() at the start of each transaction works well for environments where multiple sources may update the datastore. Because multiple clients (including WebLogic Server) may be modifying an EJB's underlying data, an initial call to ejbLoad() notifies the bean that it needs to refresh its cached data and ensures that it works against the most current version of the data.

In the special circumstance where only a single WebLogic Server instance ever accesses a particular EJB, calling ejbLoad() by default is unnecessary. Because no other clients or systems update the EJB's underlying data, WebLogic Server's cached version of the EJB data is always up-to-date. Calling ejbLoad() in this case simply creates extra overhead for WebLogic Server clients that access the bean.

To avoid unnecessary calls to ejbLoad() in the case of a single WebLogic Server instance accessing a particular EJB, WebLogic Server provides the db-is-shared deployment parameter. By default, db-is-shared is set to "true" for each EJB in the bean's weblogic-ejb-jar.xml file, which ensures that ejbLoad() is called at the start of each transaction. Where only a single WebLogic Server instance ever accesses an EJB's underlying data, you can set db-is-shared to "false" in the bean's weblogic-ejb-jar.xml file if the concurrency option is set to Exclusive. When you deploy an EJB with db-is-shared set to "false," the single instance of WebLogic Server calls ejbLoad() for the bean if:

- The EJB does not exist in the cache

- The EJB's transaction rolls back

Restrictions and Warnings for db-is-shared

Setting db-is-shared to "false" overrides WebLogic Server's default ejbLoad() container-managed-persistence behavior, regardless of whether the EJB's underlying data is updated by one WebLogic Server instance or multiple clients. If you incorrectly set db-is-shared to "false" and multiple clients (database clients, other WebLogic Server instances, and so forth) update the bean data, you run the risk of losing data integrity.

Do not set db-is-shared to "false" if you set the entity bean's concurrency strategy to the "Database" option. If you do, WebLogic Server will ignore the db-is-shared setting.

With database locking specified, the EJB container continues to cache instances of entity bean classes. However, the container does not cache the intermediate state of the EJB instance between transactions. Instead, WebLogic Server calls ejbLoad() for each instance at the beginning of a transaction to obtain the latest EJB data. This means that setting db-is-shared to "false" which prevents WebLogic Server from calling ejbload() at the beginning of each transaction is invalid.

Also, due to caching limitations, you cannot set db-is-shared to "false" in a WebLogic Server cluster.

Using is-modified-method-name to Limit Calls to ejbStore() (EJB 1.1 Only)

This method is no longer required.

Note: The is-modified-method-name deployment descriptor element applies to EJB 1.1 container-managed-persistence (CMP) beans only. This element is found in the weblogic-ejb-jar.xml file. However, it is not longer required for EJB 2.0. WebLogic Server CMP implementation automatically detects modifications of CMP fields and writes only those changes to the underlying datastore. We recommend that you do not use is-modified-method-name with bean-managed-persistence (BMP) because you would need to create both the is-modified-method-name element. and the ejbstore method.

By default, WebLogic Server calls the ejbStore() method at the successful completion (commit) of each transaction. ejbStore() is called at commit time regardless of whether the EJB's persistent fields were actually updated. WebLogic Server provides the is-modified-method-name element for cases where unnecessary calls to ejbStore() may result in poor performance.

To use is-modified-method-name, EJB providers must first develop an EJB method that "cues" WebLogic Server when persistent data has been updated. The method must return "false" to indicate that no EJB fields were updated, or "true" to indicate that some fields were modified.

The EJB provider or EJB deployment descriptors then identify the name of this method by using the value of the is-modified-method-name element. WebLogic Server calls the specified method name when a transaction commits, and calls ejbStore() only if the method returns "true." For more information on this element, see is-modified-method-name.

Warning for is-modified-method-name

Using the is-modified-method-name element can improve performance by avoiding unnecessary calls to ejbStore(). However, it places a greater burden on the EJB developer to identify correctly when updates have occurred. If the specified is-modified-method-name returns an incorrect flag to WebLogic Server, data integrity problems can occur, and they may be difficult to track down.

If entity EJB updates appear "lost" in your system, start by ensuring that the value for all is-modified-method-name elements return "true" under every circumstance. In this way, you can revert to WebLogic Server's default ejbStore() behavior and possibly correct the problem.

Using delay-updates-until-end-of-tx to Change ejbStore() Behavior

By default, WebLogic Server updates the persistent store of all beans in a transaction only at the completion (commit) of the transaction. This generally improves performance by avoiding unnecessary updates and repeated calls to ejbStore().

If your datastore uses an isolation level of READ_UNCOMMITTED, you may want to allow other database users to view the intermediate results of in-progress transactions. In this case, the default WebLogic Server behavior of updating the datastore only at transaction completion may be unacceptable. To do this, set delay-updates-until-end-of-tx to "false."

You can disable the default behavior by using the delay-updates-until-end-of-tx deployment descriptor element. This element is set in the weblogic-ejb-jar.xml file. When you set this element to "false," WebLogic Server calls ejbStore() after each method call, rather than at the conclusion of the transaction.

Note: Setting delay-updates-until-end-of-tx to false does not cause database updates to be "committed" to the database after each method invoke; they are only sent to the database. Updates are committed or rolled back in the database only at the conclusion of the transaction.

Setting Entity EJBs to Read-Only

Entity EJBs can also use the read-only concurrency strategy to modify basic ejbLoad() and ejbStore() behavior. The following sections describe how the EJB container supports the concurrency service.

You specify the read-only cache strategy by editing the concurrency-strategy element in the weblogic-ejb-jar.xml deployment file. For instructions on how to edit the deployment descriptors, see Specifying and Editing the EJB Deployment Descriptors.

Read-Only Concurrency Strategy

You can use the read-only concurrency strategy for entity EJBs that are never modified by an EJB client, but they can be updated periodically by an external source. For example, a read-only entity EJB can represent a stock quote for a particular company; the quote is updated externally to the WebLogic Server system.

WebLogic Server never calls ejbStore() for a read-only entity EJB. ejbLoad() is called initially when the EJB is created; afterwards, WebLogic Server calls ejbLoad() only at intervals defined by the read-timeout-seconds deployment parameter.

Restrictions for Read-Only Concurrency Strategy

Entity EJBs using the read-only concurrency strategy must observe the following restrictions:

- They cannot require updates to the EJB data, because WebLogic Server never calls ejbStore() for read-only entity EJBs.

- Their transaction attributes must be set to NotSupported (the beans cannot rely on a transaction).

- The EJB's method calls must be idempotent. See Session EJBs in a Cluster for more information.

- Because the bean's underlying data may be updated by an external source, calls to ejbLoad() are governed by the deployment parameter, read-timeout-seconds.

Read-Only Multicast Invalidation

Read-only multicast invalidation is an efficient means of to invalidating cached data.

Invalidate a read-only entity bean by calling the following invalidate() method on either the CachingHome or CachingLocalHome interface:

Figure 4-4 Sample code showing CachingHome and CachingLocalHome interfaces

>     package weblogic.ejb;

>     public interface CachingHome {

>     	public void invalidate(Object pk) throws RemoteException;
>     	public void invalidate (Collection pks) throws RemoteException;
>     	public void invalidateAll() throws RemoteException;

>     public interface CachingLocalHome {

>     	public void invalidate(Object pk) throws RemoteException;
>     	public void invalidate (Collection pks) throws RemoteException;
>     	public void invalidateAll() throws RemoteException

>     }

The following example codes shows how to cast the home to CachingHome and then call the method:

Figure 4-5 Sample code showing how to cast the home and call the method

>     import javax.naming.InitialContext;
>     import weblogic.ejb.CachingHome;

>     Context initial = new InitialContext();
>     Object o = initial.lookup("CustomerEJB_CustomerHome");
>     CustomerHome customerHome = (CustomerHome)o;

>     CachingHome customerCaching = (CachingHome)customerHome;
>     customerCaching.invalidateAll();

When the invalidate() method is called, the read-only entity beans are invalidated in the local server, and a multicast message is sent to the other servers in the cluster to invalidate their cached copies. The next call to an invalidated read-only entity bean causes ejbLoad to be called. ejbLoad() reads the most current version of the persistent data from the underlying datastore

WebLogic Server calls the invalidate() method after the transaction update has completed. If the invalidation occurs during a transaction update, the previous version may be read if the isolation level does not permit reading uncommitted data.

Standard Read-Only Entity Beans

WebLogic Server continues to support the standard read-only entity beans with the read-timeout element set in the deployment descriptor. If the ReadOnly option is selected in the concurrency strategy element and the read-timeout-seconds element is set in the weblogic-ejb-jar.xml file, when a read-only bean is invoked, WebLogic Server checks whether the cached data is older than the read-timeout setting. If it is, the bean's ejbLoad is called. Otherwise, the cached data is used. So, previous versions of read-only entity beans will work in this version of WebLogic Server.

Read-Mostly Pattern

WebLogic Server does not support a read-mostly cache strategy setting in weblogic-ejb-jar.xml. However, if you have EJB data that is only occasionally updated, you can create a "read-mostly pattern" by implementing a combination of read-only and read-write EJBs.

For an example of the read-mostly pattern, see the Read Mostly example in your WebLogic Server distribution:

wlserver6.1\samples\examples\ejb\extensions\readMostly

WebLogic Server provides an automatic invalidate() method for the Read-Mostly pattern. With this pattern, Read-Only entity bean and a Read-Write entity bean are mapped to the same data. To read the data, you use the Read-Only entity bean; to update the data, you use the Read-Write entity bean.

In a read-mostly pattern, a read-only entity EJB retrieves bean data at intervals specified by the read-timeout-seconds deployment descriptor element specified in the weblogic-ejb-jar.xml file. A separate read-write entity EJB models the same data as the read-only EJB, and updates the data at required intervals.

When creating a read-mostly pattern, use the following suggestions to reduce data consistency problems:

- For all read-only EJBs, set read-timeout-seconds to the same value for all beans that may be updated in the same transaction.

- For all read-only EJBs, set read-timeout-seconds to the smallest timeframe that yields acceptable performance levels.

- Ensure that all read-write EJBs in the system update only the smallest portion of data necessary; avoid beans that write numerous, unchanged fields to the datastore at each ejbStore().

- Ensure that all read-write EJBs update their data in a timely fashion; avoid involving read-write beans in long-running transactions that may span the read-timeout-seconds setting for their read-only counterparts.

Note: In a WebLogic Server cluster, clients of the read-only EJB benefit from using cached EJB data. Clients of the read-write EJB benefit from true transactional behavior, because the read-write EJB's state always matches the state of its data in the underlying datastore. See Entity EJBs in a Cluster for more information.

Read-Write Cache Strategy

The read-write strategy defines the default caching behavior for entity EJBs in WebLogic Server.

For read-write EJBs, WebLogic Server loads EJB data into the cache at the beginning of each transaction, or as described in Using db-is-shared to Limit Calls to ejbLoad(). WebLogic Server calls ejbStore() at the successful commit of a transaction, or as described under Using is-modified-method-name to Limit Calls to ejbStore() (EJB 1.1 Only).

EJBs in WebLogic Server Clusters

This section providers information on how the EJB container supports clustering services. It describes the behavior of EJBs and their associated transactions in a WebLogic Server cluster, and explains key deployment descriptors that affect EJB behavior in a cluster.

EJBs in a WebLogic Server cluster use modified versions of two key structures: the Home object and the EJB object. In a single server (unclustered) environment, a client looks up an EJB through the EJB's home interface, which is backed on the server by a corresponding Home object. After referencing the bean, the client interacts with the bean's methods through the remote interface, which is backed on the server by an EJB object.

The following figure shows EJB behavior in a single server environment.

Figure 4-6 Single server behavior

Note: Failover of EJBs work only between a remote client and the EJB.

Clustered EJBHome Objects

In a WebLogic Server cluster, the server-side representation of the Home object can be replaced by a cluster-aware "stub." The cluster-aware home stub has knowledge of EJB Home objects on all WebLogic Servers in the cluster. The clustered home stub provides load balancing by distributing EJB lookup requests to available servers. It can also provide failover support for lookup requests, because it routes those requests to available servers when other servers have failed.

All EJB types — stateless session, stateful session, and entity EJBs — can have cluster-aware home stubs. Whether or not a cluster-aware home stub is created is determined by the home-is-clusterable deployment element in weblogic-ejb-jar.xml. If you set this element to "true" (the default), ejbc calls the rmic compiler with the appropriate options to generate a cluster-aware home stub for the EJB.

The following figure shows EJB behavior in a WebLogic Server clustered environment. For an illustration of EJBs in a clustered server environment, see Figure 4-7.

Figure 4-7 Clustered server environment

Clustered EJBObjects

In a WebLogic Server cluster, the server-side representation of the EJBObject can also be replaced by a replica-aware EJBObject stub. This stub maintains knowledge about all copies of the EJBObject that reside on servers in the cluster. The EJBObject stub can provide load balancing and failover services for EJB method calls. For example, if a client invokes an EJB method call on a particular WebLogic Server and the server goes down, the EJBObject stub can failover the method call to another, running server.

Whether or not an EJB can use a replica-aware EJBObject stub depends on the type of EJB deployed and, for entity EJBs, the cache strategy selected at deployment time.

Session EJBs in a Cluster

This section describes cluster capabilities and limitations for stateful and stateless session EJBs.

Stateless Session EJBs

Stateless session EJBs can have both a cluster-aware home stub and a replica-aware EJBObject stub. By default, WebLogic Server provides failover services for EJB method calls, but only if a failure occurs between method calls. For example, failover is automatically supported if a failure occurs after a method completes, or if the method fails to connect to a server. When failures occur while an EJB method is in progress, WebLogic Server does not automatically fail over from one server to another.

This default behavior ensures that database updates within an EJB method are not "duplicated" due to a failover scenario. For example, if a client calls a method that increments a value in a datastore and WebLogic Server fails over to another server before the method completes, the datastore would be updated twice for the client's single method call.

If methods are written in such a way that repeated calls to the same method do not cause duplicate updates, the method is said to be "idempotent." For idempotent methods, WebLogic Server provides the stateless-bean-methods-are-idempotent deployment property. If you set this property to "true" in weblogic-ejb-jar.xml, WebLogic Server assumes that the method is idempotent and will provide failover services for the EJB method, even if a failure occurs during a method call.

The following figure show a stateless session EJBs in a WebLogic Server clustered environment.

Figure 4-8 Stateless session EJBs in a clustered server environment

Stateful Session EJBs

To enable stateful session EJBs to use cluster-aware home stubs, set home-is-clusterable to "true." This provides failover and load balancing for stateful EJB lookups. Stateful session EJBs configured this way use replica-aware EJBObject stubs. For more information on in-memory replication for stateful session EJBs, see In-Memory Replication for Stateful Session EJBs.

In-Memory Replication for Stateful Session EJBs

The following sections describe how the EJB Container supports replication services. The WebLogic Server EJB container supports clustering for stateful session EJBs. Whereas in WebLogic Server 5.1 only the EJBHome object is clustered for stateful session EJBs, the EJB container can also replicate the state of the EJB across clustered WebLogic Server instances.

Replication support for stateful session EJBs is transparent to clients of the EJB. When a stateful session EJB is deployed, WebLogic Server creates a cluster-aware EJBHome stub and a replica-aware EJBObject stub for the stateful session EJB. The EJBObject stub maintains a list of the primary WebLogic Server instances on which the EJB instance runs, as well as the name of a secondary WebLogic Server to use for replicating the bean's state.

Each time a client of the EJB commits a transaction that modifies the EJB's state, WebLogic Server replicates the bean's state to the secondary server instance. Replication of the bean's state occurs directly in memory, for best performance in a clustered environment.

Should the primary server instance fail, the client's next method invocation is automatically transferred to the EJB instance on the secondary server. The secondary server becomes the primary WebLogic Server for the EJB instance, and a new secondary server handles possible additional failovers. Should the EJB's secondary server fail, WebLogic Server enlists a new secondary server instance from the cluster.

Clients of a stateful session EJB are therefore guaranteed to have quick access to the latest committed state of the EJB, except under the special circumstances described in Limitations of In-Memory Replication.

Requirements and Configuration for In-Memory Replication

To replicate the state of a stateful session EJB in a WebLogic Server cluster, make sure that the cluster is homogeneous for the EJB class. In other words, deploy the same EJB class to every WebLogic Server instance in the cluster, using the same deployment descriptor. In-memory replication is not supported for heterogeneous clusters.

By default, WebLogic Server does not replicate the state of stateful session EJB instances in a cluster. This models the behavior released with WebLogic Server Version 6.0. To enable replication, set the replication-type deployment parameter in the weblogic-ejb-jar.xml deployment file to InMemory.

Figure 4-9 XML sample enabling replication

>     <stateful-session-clustering>

>     	...

>     	<replication-type>InMemory</replication-type>

>     </stateful-session-clustering>

Limitations of In-Memory Replication

By replicating the state of a stateful session EJB, clients are generally guaranteed to have the last committed state of the EJB, even if the primary WebLogic Server instance fails. However, in the following rare failover scenarios, the last committed state may not be available:

- A client commits a transaction involving a stateful EJB, but the primary WebLogic Server fails before the EJB's state is replicated. In this case, the client's next method invocation works against the previous committed state.

- A client creates an instance of a stateful session EJB and commits an initial transaction, but the primary WebLogic Server fails before the EJB's initial state can be replicated. The client's next method invocation fails to locate the bean instance, because the initial state could not be replicated. The client needs to recreate the EJB instance, using the clustered EJBHome stub, and restart the transaction.

- Both the primary and secondary servers fail. The client needs to recreate the EJB instance and restart the transaction.

Entity EJBs in a Cluster

As with all EJB types, entity EJBs can utilize cluster-aware home stubs once you set home-is-clusterable to "true." The behavior of the EJBObject stub depends on the cache-strategy deployment element in weblogic-ejb-jar.xml.

Read-Write Entity EJBs in a Cluster

read-write entity EJBs in a cluster behave similarly to entity EJBs in a non-clustered system, in that:

- Multiple clients can use the bean in transactions.

- ejbLoad() is always called at the beginning of each transaction (because the db-is-shared deployment parameter cannot be set to "false" in a cluster).

- ejbStore() behavior is governed by the rules described in ejbLoad() and ejbStore() Behavior for Entity EJBs.

Figure 4-10 shows read-write entity EJBs in a WebLogic Server clustered environment. The three arrows on Home Stub point to all three servers and show multiple client access.

Figure 4-10 Read-write entity EJBs in a clustered server environment

Note: In the preceding figure, the set of three arrows for both home stubs refers to the EJBHome on each server.

read-write entity EJBs support automatic failover on a safe exception, if home-is-clusterable is set to true. For example, failover is automatically supported if there is a failure after a method completes, or if the method fails to connect to a server.

Cluster Address

When you configure a cluster, you supply a cluster address that identifies the Managed Servers in the cluster. The cluster address is used in entity and stateless beans to construct the host name portion of URLs. If the cluster address is not set, EJB handles may not work properly. For more information on cluster addresses, see Using WebLogic Server Clusters.

Transaction Management

The following sections provide information on how the EJB container supports transaction management services. They describe EJBs in several transaction scenarios. EJBs that engage in distributed transactions (transactions that make updates in multiple datastores) guarantee that all branches of the transaction commit or roll back as a logical unit.

The current version of WebLogic Server supports Java Transaction API (JTA), which you can use to implement distributed transactional applications.

Also, two-phase commit is supported for both 1.1 and 2.0 EJBs. The two-phase commit protocol is a method of coordinating a single transaction across two or more resource managers. It guarantees data integrity by ensuring that transactional updates are committed in all participating databases, or are fully rolled back out of all the databases, reverting to the state prior to the start of the transaction. For more information on using transactions and the two-phase commit protocol, see Introducing Transactions.

Transaction Management Responsibilities

Session EJBs can rely on their own code, their client's code, or the WebLogic Server container to define transaction boundaries. EJBs can use container- or client-demarcated transaction boundaries, but they cannot define their own transaction boundaries unless they observe certain restrictions.

- In bean-managed transactions, the EJB manages the transaction demarcation. If bean- or client-managed transactions are required, you must provide the java code and use the javax.transaction.UserTransaction interface. The EJB or client can then access a UserTransaction object through JNDI and specify transaction boundaries with explicit calls to tx.begin(), tx.commit(), tx.rollback(). See Using javax.transaction.UserTransaction for more information on defining transaction boundaries.

- In container-managed transactions, the WebLogic Server EJB container manages the transaction demarcation. For EJBs that use container-managed transactions (or EJBs that mix container and bean-managed transactions) you can use several deployment elements to control the transactional requirements for individual EJB methods. For more information about the deployment descriptors, see Programming WebLogic EJB.

Note: If the EJB provider does not specify a transaction attribute for a method in the ejb-jar.xml file, WebLogic Server uses the supports attribute by default.

The sequence of transaction events differs between container-managed and bean-managed transactions.

Using javax.transaction.UserTransaction

To define transaction boundaries in EJB or client code, you must obtain a UserTransaction object and begin a transaction before you obtain a Java Transaction Service (JTS) or JDBC database connection. If you start a transaction after obtaining a database connection, the connection has no relationship to the new transaction, and there are no semantics to "enlist" the connection in a subsequent transaction context. If a JTS connection is not associated with a transaction context, it operates similarly to a standard JDBC connection that has autocommit equal to true, and updates are automatically committed to the datastore.

Once you create a database connection within a transaction context, that connection becomes "reserved" until the transaction either commits or rolls back. To maintain performance and throughput for your applications, always ensure that your transaction completes quickly, so that the database connection can be released and made available to other client requests. See Preserving Transaction Resources for more information.

Note: You can associate only a single database connection with an active transaction context.

Restriction for Container-Managed EJBs

You cannot use the javax.transaction.UserTransaction method within an EJB that uses container-managed transactions.

Transaction Isolation Levels

The method for setting the transaction isolation level differs according to whether your application uses bean-managed or container-managed transaction demarcation. The following sections examine each of these scenarios.

Setting User Transaction Isolation Levels

You set the isolation level for user transactions in the beans java code. When the application runs, the transaction is explicitly started. See Figure 4-11 for a code sample of how to set the level.

Figure 4-11 Sample Java Code setting user transaction isolation levels

>     import javax.transaction.Transaction;
>     import java.sql.Connection
>     import weblogic.transaction.TxHelper:
>     import weblogic.transaction.Transaction;
>     import weblogic.transaction.TxConstants;

>     User Transaction tx = (UserTransaction)

>     ctx.lookup("javax.transaction.UserTransaction");

>     //Begin user transaction

>     	tx.begin();

>     //Set transaction isolation level to TRANSACTION_READ_COMMITED

>     Transaction tx = TxHelper.getTransaction();
>     	tx.setProperty (TxConstants.ISOLATION_LEVEL, new Integer
>     	 (Connection.TRANSACTION_READ_COMMITED));

>     //perform transaction work

>     	tx.commit();

Setting Container-Managed Transaction Isolation Levels

You set the isolation level for container-managed transactions in the transaction-isolation element of the weblogic-ejb-jar.xml deployment file. WebLogic Server passes this value to the underlying database. The behavior of the transaction depends both on the EJB's isolation level setting and the concurrency control of the underlying persistent store. For more information on setting container-managed transaction isolation levels, see Programming WebLogic JTA.

Limitations of TRANSACTION_SERIALIZABLE

Many datastores provide limited support for detecting serialization problems, even for a single user connection. Therefore, even if you set transaction-isolation to TRANSACTION_SERIALIZABLE, you may experience serialization problems due to the limitations of the datastore.

Refer to your RDBMS documentation for more details about isolation level support.

Special Note for Oracle Databases

Oracle uses optimistic concurrency. As a consequence, even with a setting of TRANSACTION_SERIALIZABLE, Oracle does not detect serialization problems until commit time. The message returned is:

>     java.sql.SQLException: ORA-08177: can't serialize access for this
>     transaction

Even if you use the TRANSACTION_SERIALIZABLE setting for an EJB, you may receive exceptions or rollbacks in the EJB client if contention occurs between clients for the same rows. To avoid these problems, make sure that the code in your client application catches and examines the SQL exceptions, and take you take the appropriate action to resolve the exceptions, such as restarting the transaction.

With WebLogic Server, you can set the isolation level for transactions to TRANSACTION_READ_COMMITTED_FOR_UPDATE for methods on which this option is defined. When set, every SELECT query from that point on will have FOR_UPDATE added to require locks on the selected data. This condition remains in effect until the transaction does a COMMIT or ROLLBACK.

Distributing Transactions Across Multiple EJBs

WebLogic Server does support transactions that are distributed over multiple datasources; a single database transaction can span multiple EJBs on multiple servers. You can explicitly enable support for these types of transactions by starting a transaction and invoking several EJBs. Or, a single EJB can invoke other EJBs that implicitly work within the same transaction context. The following sections describe these scenarios.

Calling Multiple EJBs from a Single Transaction Context

In the following code fragment, a client application obtains a UserTransaction object and uses it to begin and commit a transaction. The client invokes two EJBs within the context of the transaction. The transaction attribute for each EJB is set to Required:

Figure 4-12 Beginning and committing a transaction

>     import javax.transaction.*;

>     ...

>     u = (UserTransaction)
>     jndiContext.lookup("javax.transaction.UserTransaction");

>     u.begin();

>     account1.withdraw(100);

>     account2.deposit(100);

>     u.commit();

>     ...

In the above code fragment, updates performed by the "account1" and "account2" EJBs occur within the context of a single UserTransaction. The EJBs commit or roll back as a logical unit. This is true regardless of whether "account1" and "account2" reside on the same WebLogic Server, multiple WebLogic Servers, or a WebLogic Server cluster.

The only requirement for wrapping EJB calls in this manner is that both "account1" and "account2" must support the client transaction. The beans' trans-attribute element must be set to Required, Supports, or Mandatory.

Encapsulating a Multi-Operation Transaction

You can also use a "wrapper" EJB that encapsulates a transaction. The client calls the wrapper EJB to perform an action such as a bank transfer. The wrapper EJB responds by starting a new transaction and invoking one or more EJBs to do the work of the transaction.

The "wrapper" EJB can explicitly obtain a transaction context before invoking other EJBs, or WebLogic Server can automatically create a new transaction context, if the EJB's trans-attribute element is set to Required or RequiresNew. The trans-attribute element is set in the ejb-jar.xml file. All EJBs invoked by the wrapper EJB must be able to support the transaction context (their trans-attribute elements must be set to Required, Supports, or Mandatory).

Distributing Transactions Across EJBs in a WebLogic Server Cluster

WebLogic Server provides additional transaction performance benefits for EJBs that reside in a WebLogic Server cluster. When a single transaction utilizes multiple EJBs, WebLogic Server attempts to use EJB instances from a single WebLogic Server instance, rather than using EJBs from different servers. This approach minimizes network traffic for the transaction.

In some cases, a transaction can use EJBs that reside on multiple WebLogic Server instances in a cluster. This can occur in heterogeneous clusters, where all EJBs have not been deployed to all WebLogic Server instances. In these cases, WebLogic Server uses a multitier connection to access the datastore, rather than multiple direct connections. This approach uses fewer resources, and yields better performance for the transaction.

However, for best performance, the cluster should be homogeneous — all EJBs should reside on all available WebLogic Server instances.

Delay-Database-Insert-Until

By default, the database insert occurs after the client calls the ejbPostCreate method. To delay having WebLogic Server insert the new bean, use the delay-database-insert-until element in the weblogic-cmp-rdbms-jar.xml file to specify the precise time at which a new bean that uses RDBMS CMP is inserted into the database.

Delaying the database insert until after ejbPostCreate is required when a cmr-field is mapped to a foreign-key column that does not allow null values. In this case, set the cmr-field to a non-null value in ejbPostCreate before the bean is inserted into the database.

Note: The cmr-fields may not be set during a ejbCreate method call, before the primary key of the bean is known.

BEA recommend that you specify the delay the database insert until after ejbPostCreate if the ejbPostCreate method modifies the persistent fields of the bean. Doing so yields better performance by avoiding an unnecessary store operation.

For maximum flexibility, avoid creating related beans in their ejbPostCreate method. The creation of these additional instances may make delaying the database insert impossible if database constraints prevent related beans from referring to a bean that has not yet been created.

The allowed values for the delay-database-insert-until element are:

- ejbCreate - This method performs a database insert immediately after ejbCreate.

- ejbPostCreate - This method performs an insert immediately after ejbPostCreate (default).

  Figure 4-13 Sample xml specifying the delay-database-insert until element

  >     <delay-database-insert-until>ejbPostCreate</delay-database-insert
  >     -until> -->

Resource Factories

The following sections provide information on how the EJB container supports resource services. In WebLogic Server, EJBs can access JDBC connection pools by directly instantiating a JDBC pool driver. However, it is recommended that you instead bind a JDBC datasource resource into the WebLogic Server JNDI tree as a resource factory.

Using resource factories enables the EJB to map a resource factory reference in the EJB deployment descriptor to an available resource factory in a running WebLogic Server. Although the resource factory reference must define the type of resource factory to use, the actual name of the resource is not specified until the bean is deployed.

The following sections explain how to bind JDBC datasource and URL resources to JNDI names in WebLogic Server.

Note: WebLogic Server also supports JMS connection factories.

Setting Up JDBC Datasource Factories

Follow these steps to bind a javax.sql.DataSource resource factory to a JNDI name in WebLogic Server. Note that you can set up either a transactional or non-transactional JDBC datasource as necessary:

1. Set up a JDBC connection pool in the Administration Console. See Managing JDBC Connectivity in the Administration Guide for more information.

2. Start WebLogic Server.

3. Start WebLogic Server Administration Console.

4. In the Console, click the Services node and expand JDBC.

5. Select Data Sources and choose the Configure a new JDBC Data Source option.

6. Enter the Name, JNDI Name, and Pool Name. Check to enable Row Prefetch if you if you want to prefetch rows between client and WebLogic Server for each resultSet and then specify the Row Prefetch Size and Stream Chunk Size.

   1. For non-transactional JDBC data sources, enter the full WebLogic Server JNDI name to bind to the datasource and the name of the WebLogic Server connection pool.

   2. For transactional JDBC data sources, enter the full WebLogic Server JNDI name to bind to the transactional datasource and the name of the WebLogic Server connection pool.

      For more information on configuring transactional and non-transactional data sources, see Configure a JDBC Data Source.

7. Click Create to save the new JDBC Data Source.

8. Bind the JNDI name of the datasource to the EJB's local JNDI environment by doing one of the following:

   Map an existing EJB resource factory reference to the JNDI name by directly editing the resource-description element in the weblogic.ejb-jar.xml deployment file. See Specifying and Editing the EJB Deployment Descriptors for instructions on editing deployment descriptors.

Setting Up URL Connection Factories

To set up a URL connection factory in WebLogic Server, bind a URL string to a JNDI name using these instructions:

1. In a text editor, open the config.xml file for the instance of the WebLogic Server you are using and set the URLResource attribute for the following config.xml elements:

   - WebServer

   - VirtualHost:

2. Set the URLResource attribute for the WebServer element using the following syntax:

   >     <WebServer URLResource="weblogic.httpd.url.testURL=http://
   >     localhost:7701/testfile.txt" DefaultWebApp="default-tests"/>

3. Set the URLResource attribute for the VirtualHost element, when virtual hosting is required, using the following syntax:

   >     <VirtualHostName=guestserver" targets="myserver,test_web_server
   >     "URLResource="weblogic.httpd.url.testURL=http://
   >     localhost:7701/testfile.txt" VirtualHostNames="guest.com"/>

4. Save the changes in the config.xml file and reboot WebLogic Server

Locking Services for Entity EJBs

The following sections describe how the EJB Container supports locking services. The WebLogic Server container supports both the database locking and exclusive locking mechanisms. The default and recommended mechanism for EJB 1.1 and EJB 2.0 beans is database locking.

Exclusive Locking Services

Exclusive locking was the default in WebLogic Server 5.1 and 4.5.1. This method of locking provides reliable access to EJB data, and avoids unnecessary calls to ejbLoad() to refresh the EJB instance's persistent fields. However, exclusive locking does not provide the best model for concurrent access to the EJB's data. Once a client has locked an EJB instance, other clients are blocked from the EJB's data even if they intend only to read the persistent fields.

The EJB container in WebLogic Server can use exclusive locking mechanism for entity EJB instances. As clients enlist an EJB or EJB method in a transaction, WebLogic Server places an exclusive lock on the EJB instance for the duration of the transaction. Other clients requesting the same EJB or method are blocked until the current transaction completes.

Database Locking Services

Database locking is the default for WebLogic Server 6.1. It improves concurrent access for entity EJBs. The WebLogic Server container defers locking services to the underlying database. Unlike exclusive locking, the underlying data store can provide finer granularity for locking EJB data, and deadlock detection.

With the database locking mechanism, the EJB container continues to cache instances of entity EJB classes. However, the container does not cache the intermediate state of the EJB instance between transactions. Instead, WebLogic Server calls ejbLoad() for each instance at the beginning of a transaction to obtain the latest EJB data. The request to commit data is subsequently passed along to the database. The database, therefore, handles all lock management and deadlock detection for the EJB's data.

Deferring locks to the underlying database improves throughput for concurrent access to entity EJB data, while also providing deadlock detection. However, using database locking requires more detailed knowledge of the underlying datastore's lock policies, which can reduce the EJB's portability among different systems.

Setting Up Database Locking

You specify the locking mechanism used for an EJB by setting the concurrency-strategy deployment parameter in weblogic-ejb-jar.xml. You set concurrency-strategy at the individual EJB level, so that you can mix locking mechanisms within the EJB container.

The following excerpt from weblogic-ejb-jar.xml shows an EJB that uses database locking.

Figure 4-14 Database locking sample

>     <entity-descriptor>

>     	<entity-cache>

>     	...

>     	<concurrency-strategy>Database</concurrency-strategy>

>     	</entity-cache>

>     	...

>     </entity-descriptor>

If you do not specify concurrency-strategy, WebLogic Server performs database locking for entity EJB instances, as described in Database Locking Services.

Copyright © 2001 BEA Systems, Inc. All rights reserved. Required browser: Netscape 4.0 or higher, or Microsoft Internet Explorer 4.0 or higher.