Corporate Info | News | Solutions | Products | Partners | Services | Events | Download | How To Buy
BEA WebLogic Server Enterprise JavaBeans 1.1: Previous topic | Next topic | Contents

The WebLogic Server EJB Container

Overview

EJB Lifecycle in WebLogic Server

Stateless session EJB lifecycle

Initializing EJB instances

Activating and pooling EJBs

Stateful EJB lifecycle

Initializing and using EJB instances

Passivating stateful EJBs

Removing stateful session EJB instances

Stateful session EJB requirements

Locking Model for Entity EJBs

ejbLoad() and ejbStore() behavior for entity EJBs

Using db-is-shared to limit calls to ejbLoad()

Restrictions and warnings for db-is-shared

Using is-modified-method-name to limit calls to ejbStore()

Warning for is-modified-method-name

Using delay-updates-until-end-of-tx to change ejbStore() behavior

Setting the cache strategy for entity EJBs

read-write cache strategy

read-only cache strategy

"read-mostly" pattern

EJBs in WebLogic Server Clusters

Overview

Clustered EJBHome objects

Clustered EJBObjects

Session EJBs in a cluster

Stateless session EJBs

Stateful session EJBs

Entity EJBs in a cluster

read-write entity EJBs

read-only entity EJBs

Transaction management

Transaction management responsibilities

Using javax.transaction.UserTransaction

Restriction for container-managed EJBs

Distributing transactions across multiple EJBs

Calling multiple EJBs from a single transaction context

Encapsulating a multi-operation transaction

Distributing transactions across EJBs in a WebLogic Server cluster

Transaction isolation level

Limitations of TRANSACTION_SERIALIZABLE

Special note for Oracle Databases

Resource Factories

Setting up JDBC datasource factories

Setting up URL connection factories

Setting up javax.mail.Session resources

Persistence Services

Using WebLogic Server RDBMS Persistence

Writing Finders for RDBMS Persistence

Using WebLogic Query Language (WLQL)

Using Java Expressions in WLQL

Overview

This section describes the services that are available to EJBs using the WebLogic Server container. It includes these topics:

- EJB Lifecycle in WebLogic Server

- ejbLoad() and ejbStore() behavior for entity EJBs

- EJBs in WebLogic Server Clusters

- Transaction management

- Resource Factories

- Persistence Services

See the Overview of WebLogic Enterprise JavaBeans for a basic introduction to EJB in WebLogic Server.

EJB Lifecycle in WebLogic Server

The following sections describe the lifecycle 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.

Stateless session EJB lifecycle

WebLogic Server uses a free pool to improve performance and throughput for stateless session 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.

Initializing EJB instances

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

You can optionally set the initial-beans-in-free-pool property in weblogic-ejb-jar.xml to automatically create unbound EJBs in the free pool during startup. This can improve response time when accessing 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 either by available memory, or the value of the max-beans-in-free-pool deployment element.

Activating and pooling EJBs

When a client calls a method on a stateless EJB, WebLogic Server obtains an instance from the free pool. The EJB remains active for the duration of the client's method call. After the method completes, the EJB 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 block 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 EJB lifecycle

Note: This section describes the lifecycle of both stateful session EJBs and entity EJBs in WebLogic Server.

WebLogic Server uses a cache of bean instances to improve the performance of stateful EJBs. The cache stores active EJB instances in memory so that they are immediately available for client requests. Active EJBs consist of instances that are currently in use by a client, as well as instances that were recently in use, as described below. The cache is unlike the free pool insofar as beans in the cache are bound either to a particular client (as with stateful session beans) or to a primary key (as with entity beans).

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

Initializing and using EJB instances

No stateful EJB instances exist in WebLogic Server at startup time. (Entity EJBs logically exist in a datastore, but they do not yet exist from the WebLogic Server perspective.) As clients look up and obtain references to individual beans, WebLogic Server initializes new instances of the EJB class and stores them in the cache.

While in cache, the EJBs can be quickly accessed by clients. WebLogic Server locks a cached instance of an entity EJB only for the duration of a transaction. If the EJB is not involved in a transaction, the instance is locked only for the duration of each method invoke. This means that multiple clients can access the same entity EJB in a serial fashion, but only if the bean is not involved in a transaction. See Locking Model for Entity EJBs for more information.

Passivating stateful EJBs

To achieve high performance, WebLogic Server reserves the cache for EJBs that clients are currently using and EJBs that were recently in use. When EJBs no longer meet these criteria, they become eligible for passivation. Passivation is the process WebLogic Server uses to remove an EJB from cache while preserving the EJB's state on disk. While passivated, EJBs use minimal WebLogic Server resources, but they are not immediately available for client requests (as they are while in the cache).

Note: Stateful session EJBs must abide by certain rules to ensure that bean fields can be serialized to persistent storage. See Stateful session EJB requirements for more information.

WebLogic Server provides the max-beans-in-cache deployment element, which provides some control over when EJBs are passivated.

If max-beans-in-cache is reached and there are EJBs in cache that are not being used, WebLogic Server passivates some of those beans. This occurs even if the unused beans have not reached their idle-timeout-seconds limit (described below). If max-beans-in-cache is reached and all EJBs in the cache are being used by clients, WebLogic Server throws a CacheFullException.

Note: When an EJB becomes eligible for passivation, it does not mean that WebLogic Server passivates the bean immediately. In fact, the bean may not be passivated at all. Passivation occurs only when the EJB is eligible for passivation and there is pressure on server resources, or when WebLogic Server performs regular cache maintenance.

Removing stateful session EJB instances

The max-beans-in-cache and idle-timeout-seconds deployment elements also provide some control over when stateful session EJBs are removed from the cache or from disk:

- For cached EJB instances: When resources become scarce and there is a need for memory in the cache, WebLogic Server examines EJB classes that are approaching their max-beans-in-cache limit. Of those beans, WebLogic Server takes EJB instances that have not been used for idle-timeout-seconds and removes them from the cache (rather than passivating them to disk). Removing, rather than passivating, the instance ensures that "inactive" EJBs do not consume cache or disk resources in WebLogic Server.

  If a stateful bean has been idle for longer than idle-timeout-seconds, WebLogic Server may remove the instance from memory as a result of regular cache maintenance, even if EJB's max-beans-in-cache limit has not been reached.

  Note: Setting idle-timeout-seconds to 0 stops WebLogic Server from removing EJBs as part of regular cache maintenance. However, EJBs may still be passivated if cache resources become scarce.

- For passivated EJB instances: After a stateful session EJB instance has been passivated, a client must use the EJB instance before idle-timeout-seconds is reached. Otherwise, WebLogic Server removes the passivated instance from disk.

Stateful session EJB requirements

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. With the EJB 1.1 specification, an EJB's non-transient fields can also include:

- a reference to the EJB's JNDI environment context

- a reference to the UserTransaction object

As of the EJB 1.1 specification, references to the javax.ejb.SessionContext object cannot be declared transient.

Locking Model for Entity EJBs

The EJB 1.1 container in WebLogic Server Version 5.1 uses a pessimistic 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 or method for the duration of the transaction. Other clients requesting the same EJB or method block until the current transaction completes.

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, in certain circumstances pessimistic locking may 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.

To improve concurrent access for entity EJB's, the WebLogic Server EJB 2.0 container enables you to defer locking services to the underlying database. In most cases, the underlying data store can provide finer granularity for locking EJB data, and improve throughput for concurrent access to the bean's data. See EJB 2.0 for BEA WebLogic Server Overview for more information.

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. First, 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 data store.

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 data store 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 parameters 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. Since multiple clients (including WebLogic Server) may be modifying an EJB's underlying data, an initial call to ejbLoad() refreshes the bean's cached data and ensures that the transaction works against the most up-to-date version of the bean.

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

To avoid unnecessary calls to ejbLoad() in this special case, WebLogic Server provides the db-is-shared deployment parameter. By default, db-is-shared is set to "true" for each EJB, which ensures that ejbLoad() is called at the start of each transaction. In the special case 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. When you deploy an EJB with db-is-shared set to "false," WebLogic Server calls ejbLoad() for the bean only when:

- a client first references the EJB

- the EJB's transaction is rolled back

Restrictions and warnings for db-is-shared

Setting db-is-shared to "false" overrides WebLogic Server's default ejbLoad() 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.

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()

By default, WebLogic Server calls ejbStore() at the successful completion (commit) of each transaction. ejbStore() is called at commit time regardless of whether or not the EJB's persistent fields were actually updated. WebLogic Server provides the is-modified-method-name deployment parameter 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 deployer then identifies the name of this method using the is-modified-method-name element in weblogic-ejb-jar.xml. WebLogic Server calls the specified method name when a transaction commits, and calls ejbStore() only if the method returns "true."

Note: You can use is-modified-method-name with entity EJBs that use either container-managed or bean-managed persistence services.

Warning for is-modified-method-name

is-modified-method-name can improve performance by avoiding unnecessary calls to ejbStore(). However, it places a greater burden on the EJB developer to correctly identify 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 to become "lost" in your system, start by ensuring that all is-modified-method-name methods 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.

You can disable the default behavior by using the delay-updates-until-end-of-tx deployment element. 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-txt 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.

See Setting cache and performance properties for information on changing this deployment element using EJB Deployer.

Setting the cache strategy for entity EJBs

Entity EJBs can also use one of two cache strategies to modify basic ejbLoad() and ejbStore() behavior:

- read-write

- read-only

You can set the cache strategy with EJB Deployer by using the instructions in Setting cache and performance properties, or by directly editing the cache-strategy element in the weblogic-ejb-jar.xml deployment file.

read-write cache strategy

The read-write strategy defines the default caching behavior for entity EJBs in WebLogic Server. With read-write entity EJBs, multiple clients can use the same bean instance in transactions, and data integrity is ensured.

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().

read-only cache strategy

The read-only cache strategy can be used for entity EJBs that are never modified by an EJB client, but may be updated periodically by an external source. For example, a read-only entity EJB may be used to represent a stock quote for a particular company, which 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 EJBs

Entity EJBs using the read-only cache 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, because WebLogic Server assumes they are idempotent and will failover method calls if necessary in a cluster. See EJBs in WebLogic Server Clusters 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-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.

In a "read-mostly" pattern, a read-only entity EJB retrieves bean data at intervals specified by read-timeout-seconds. A separate read-write entity EJB models the same data as the read-only EJB, and updates the data at required intervals. See the read-mostly EJB example for more information.

When creating a read-mostly pattern, use the following suggestions to reduce the likelihood of 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 that 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, since 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.

EJBs in WebLogic Server Clusters

This section describes the behavior of EJBs and their associated transactions in a WebLogic Server cluster, and explains key deployment properties that affect EJB behavior in a cluster.

Overview

EJBs in a WebLogic Server cluster operate using 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 via 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 via the remote interface, which is backed on the server by an EJB object.

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 EJBHome 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 support failover support for lookup requests, since 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 is created is determined by the home-is-clusterable deployment property in weblogic-ejb-jar.xml. If this property is set to "true" (the default), ejbc calls the rmic compiler with the appropriate options to generate a cluster-aware home stub for the EJB.

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 utilize a replica-aware EJBObject stub depends on the type of EJB deployed and, for entity EJBs, the cache strategy selected at deployment time. The sections that follow describe cluster capabilities and limitations for different EJB types.

Session EJBs in a cluster

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 there is a failure 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 failover 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 which 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.

Stateful session EJBs

Stateful session EJBs can utilize cluster-aware home stubs by setting home-is-clusterable to "true." This provides failover and load balancing for stateful EJB lookups. Stateful session EJBs cannot utilize replica-aware EJBObject stubs, and WebLogic Server does not provide failover services for method calls to stateful session EJBs.

If you require cluster failover services for stateful objects, consider implementing the stateful session EJB as a servlet. Servlets can maintain state through failover in a cluster using either JDBC, an operating system file, or directly in memory. See Using session tracking from a servlet for more information.

Entity EJBs in a cluster

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

read-write entity EJBs

read-write entity EJBs in a cluster behave in a similar fashion 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 (since the db-is-shared deployment parameter cannot be set to "false" in a cluster)

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

read-write entity EJBs do not use a clustered EJBObject stub; a client's method calls to a particular EJB always go to a single WebLogic Server instance. If the server that a client is using fails, the client must re-find the entity EJB using the cluster-aware home stub.

read-write entity EJBs are not cached on individual WebLogic Server instances. As clients of a given EJB use the bean in transactions, the WebLogic Server instance passes the transaction to the underlying datastore. This approach preserves data integrity for clustered entity EJBs by allowing the backing datastore to manage all transactional locking.

read-only entity EJBs

In a clustered environment, WebLogic Server implements a fully replica-aware EJBObject stub for read-only entity EJBs. This provides load-balancing and failover capabilities for method calls to the beans. Because WebLogic Server assumes read-only beans do not modify their data, it treats the bean's methods as if they were idempotent; if a server fails during a method call, WebLogic Server automatically restarts the method using an available server.

WebLogic Server calls ejbLoad() for read-only beans once when the bean is first created. Afterwards, calls to ejbLoad() are done at regular intervals determined by the read-timeout-seconds deployment property, to refresh the bean data. ejbStore() is never called for read-only entity EJBs.

Transaction management

The following sections describe EJBs in several transaction scenarios. Note that in all cases EJB transactions should be restricted to a single persistent store, because WebLogic Server does not provide a two-phase commit protocol. EJBs that engage in distributed transactions (transactions that make updates in multiple datastores) cannot guarantee that all branches of the transaction commit or roll back as a logical unit.

The current version of WebLogic Server supports Java Messaging Service (JMS), which can be used for implementing distributed transactional applications. Also, WebLogic Enterprise supports the two-phase commit protocol.

Transaction management responsibilities

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

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

For EJBs that use container-managed transactions (or EJBs that mix container and bean-managed transactions) the EJB 1.1 specification defines several deployment elements to control the transactional requirements for individual EJB methods. See Setting method transaction attributes for information on changing this deployment element using EJB Deployer.

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.

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 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 similar to a standard JDBC connection, and updates are automatically committed to the datastore.

Once you have created 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 Preserve transaction resources in WebLogic Server EJB Design and Development for more information.

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

Restriction for container-managed EJBs

For container-managed entity EJBs, you can use the javax.transaction.UserTransaction interface or access a transactional JDBC connection from within an EJB method. However, you must ensure that the transaction does not access the bean's container-managed database fields. Also note that the nested transaction in the EJB method ultimately commits or rolls back depending on the fate of the entity EJB transaction.

Distributing transactions across multiple EJBs

Although WebLogic Server does not support transactions that are distributed over multiple datasources, a single database transaction can span multiple EJBs on multiple servers. This can be accomplished explicitly by starting a transaction and invoking several EJBs. Or, a single EJB may 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 has been set to Required:

    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 - they 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.

This type of transaction operates in a similar manner to the scenario described in Calling multiple EJBs from a single transaction context. The "wrapper" EJB may explicitly obtain a transaction context before invoking other EJBs, or WebLogic Server may automatically create a new transaction context if the EJB's trans-attribute element is set to Required or RequiresNew. 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 may utilize 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 multi-tier 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.

Transaction isolation level

The isolation level for transactions is set in the transaction-isolation element of the weblogic-cmp-rdbms-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.

To mirror the transaction behavior in earlier versions of WebLogic Server, set transaction-isolation to a value that is consistent with the default isolation level for your data store.

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

Keep in mind that 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, you must ensure that clients catch and examine the SQL exceptions, and take appropriate action, such as restarting the transaction.

Resource Factories

In WebLogic Server Version 5.1, EJBs can access JDBC connection pools by directly instantiating a JDBC driver. However it is recommended that you instead bind a JDBC resource into the WebLogic Server JNDI tree as a resource factory.

Using resource factories enables the EJB deployer 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, URL, and Java mail resources to JNDI names in WebLogic Server. See Mapping resource factory references for information on mapping JNDI names to resource factory references using EJB Deployer.

Note: WebLogic Server also supports JMS connection factories (as described in the EJB 1.1 specification).

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 setup either a transactional or non-transactional JDBC datasource as necessary:

1. Set up a JDBC connection pool in your weblogic.properties file. See Using connection pools for more information.

2. Open your weblogic.properties file using a text editor.

3. For non-transactional JDBC datasources, add the property:

       weblogic.jdbc.DataSource.jndi_name=pool_name

   where jndi_name is the full WebLogic Server JNDI name to bind to the datasource and pool_name is the name of the WebLogic Server connection pool you created in step 1.

   For example, to setup a non-transactional connection pool for demonstration purposes, you might define the property:

       weblogic.jdbc.DataSource.weblogic.jdbc.demoPool=demoPool

   This binds a transactional datasource for the "demoPool" pool to the JNDI name, "weblogic.jdbc.demoPool".

4. For transactional JDBC datasources, add the property:

       weblogic.jdbc.TXDataSource.jndi_name=pool_name

   where jndi_name is the full WebLogic Server JNDI name to bind to the transactional datasource and pool_name is the name of the WebLogic Server connection pool you created in step 1.

   For example, to setup a non-transactional connection pool for demonstration purposes, you might define the property:

       weblogic.jdbc.TXDataSource.weblogic.jdbc.jts.demoPool=demoPool

   This binds a transactional datasource for the "demoPool" pool to the JNDI name, "weblogic.jdbc.jts.demoPool".

5. Save the changes to weblogic.properties and reboot WebLogic Server.

6. Bind the JNDI name of the datasource to the EJB's local JNDI environment. To do this:

   - Use the EJB Deployer utility to map an existing EJB resource factory reference to the JNDI name, as described in Mapping resource factory references, or

   - Directly edit the resource-description tag in the weblogic.ejb-jar.xml deployment file using a text editor

Setting up URL connection factories

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

1. Open your weblogic.properties file using a text editor.

2. Add a weblogic.httpd.URLResource property for each URL you want to map to a JNDI name. Use the syntax:

       weblogic.httpd.URLResource.jndi_name=url_string

   where jndi_name is the full WebLogic Server JNDI name to bind to the URL factory and url_string is the URL to map. For example, the following entry binds the specified URL to the WebLogic Server JNDI name, "BankApp.urls.AdminServlet:"

       weblogic.httpd.URLResource.BankApp.urls.AdminServlet=http://bigserver.bankapp.com:7001/bankapp/admin

3. Save the changes to weblogic.properties and reboot WebLogic Server.

4. Bind the JNDI name of the connection factory to the EJB's local JNDI environment. To do this:

   - Use the EJB Deployer utility to map an existing EJB resource factory reference to the JNDI name, as described in Mapping resource factory references, or

   - Directly edit the resource-description tag in the weblogic.ejb-jar.xml deployment file using a text editor

Setting up javax.mail.Session resources

EJBs in WebLogic Server can use the javax.mail.Session class to send mail over various mail APIs. To setup a javax.mail.Session resource for use with WebLogic Server:

1. Open your weblogic.properties file using a text editor.

2. Add a weblogic.resource.MailSession property for each javax.mail.Session resource you want to use. The syntax is:

       weblogic.resource.MailSession.jndi_name=

             mail.from=user_name,

             mail.host=host_name

   The jndi_name is the full WebLogic Server JNDI name to bind to the javax.mail.Session resource. user_name specifies the mail address used for EJBs that access the resource factory, and host_name specifies the host that processes outgoing mail messages. For example:

       weblogic.resource.MailSession.weblogic.resource.mail.testSession=\

             mail.from=joe@company_name.com, \

             mail.host=smtp.company_name.com

3. Save the changes to weblogic.properties and reboot WebLogic Server.

4. Bind the JNDI name of the mail resource to the EJB's local JNDI environment. To do this:

   - Use the EJB Deployer utility to map an existing resource reference to the JNDI name, as described in Mapping resource factory references, or

   - Directly edit the resource-description tag in the weblogic.ejb-jar.xml deployment file using a text editor

Persistence Services

An entity EJB can save its state in any transactional or non-transactional persistent storage ("bean-managed persistence"), or it can ask the container to save its non-transient instance variables automatically ("container-managed persistence"). WebLogic Server allows both choices - even a mixture of the two.

If an EJB uses container-managed persistence, the weblogic-ejb-jar.xml deployment file specifies the type of persistence services that an EJB uses. High-level definitions for automatic persistence services are stored in the persistence-type and persistence-use elements. persistence-type defines one or more automatic services that the EJB may use. persistence-use defines the actual service that the EJB uses at deployment time.

Automatic persistence services use additional deployment files to specify their deployment properties, and to define entity EJB finder methods. For example, WebLogic Server RDBMS-based persistence services obtain deployment properties and finder definitions from a particular bean using the bean's weblogic-cmp-rdbms-jar.xml file, described below in Using WebLogic Server RDBMS Persistence.

Third-party persistence services may use other file formats to configure deployment properties. However, regardless of the file type, the configuration file must be referenced in the persistence-type and persistence-use elements in weblogic-ejb-jar.xml.

Using WebLogic Server RDBMS Persistence

To use WebLogic Server RDBMS-based persistence, you must create a dedicated XML deployment file and define the persistence elements for each EJB that will use container-managed persistence. If this file is created by WebLogic Server utilities, such as DDConverter or EJB Deployer, it is named weblogic-cmp-rdbms-jar.xml. If you create the file from scratch, you can save it to a different filename. However, you must ensure that the persistence-type and persistence-use elements in weblogic-ejb-jar.xml refer to the correct files.

weblogic-cmp-rdbms-jar.xml defines the persistence properties for a single EJB using WebLogic Server RDBMS-based persistence services. If you use multiple EJBs with RDBMS-based persistence, you must create and reference a distinct XML file for each bean.

Each weblogic-cmp-rdbms-jar.xml defines the following persistence properties:

- EJB connection pools

- EJB field to database element mappings

- Finder method definitions

The WebLogic Server EJB Deployer provides a graphical interface for configuring an entity EJB's persistence properties. See Configuring persistence properties for entity EJBs for more information.

Writing Finders for RDBMS Persistence

For EJBs that use RDBMS persistence, WebLogic Server Version 5.1 provides an easy way to write dynamic finders. The EJB provider writes the method signature of a finder in the EJBHome interface, and defines the finder's query expressions in the weblogic-cmp-rdbms-jar.xml deployment file.

ejbc creates implementations of the finder methods at deployment time, using the expressions in weblogic-cmp-rdbms-jar.xml.

The key components of a finder for RDBMS persistence are:

- The finder method signature in EJBHome.

- A finder-list stanza in the weblogic-cmp-rdbms-jar.xml deployment file.

- A finder-query stanza defined within finder.

- An optional set of finder-expression stanzas within finder.

The following sections explain how to write EJB finders using XML elements in WebLogic Server deployment files. You can also use the EJB Deployer graphical interface to create and edit finder methods, as described in Configuring persistence properties for entity EJBs.

Finder signature

EJB providers specify finder method signatures using the form find MethodName(). Finder methods defined in weblogic-cmp-rdbms-jar.xml must return a Java collection of EJB objects.

Note: EJB providers can also define a findByPrimaryKey(primkey) method that returns a single object of the associated EJB class. A single-object finder method of this signature is required by the EJB 1.1 specification. If the EJB provider does not define a findByPrimaryKey(primkey) method, WebLogic Server creates a default implementation.

finder-list stanza

The finder-list stanza associates one or more finder method signatures in EJBHome with the queries used to retrieve EJB objects. The following is an example of a simple finder-list stanza using WebLogic Server RDBMS-based persistence:

    <finder-list>

          <finder>

               <method-name>findBigAccounts</method-name>

               <method-params>

                    <method-param>double</method-param>

               </method-params>

               <finder-query><![CDATA[(> balance $0)]]></finder-query>

          </finder>

    </finder-list>

Note: If you use a non-primitive data type in a method-param element, you must specify a fully qualified name. For example, use java.sql.Timestamp rather than Timestamp. If you do not use a qualified name, ejbc generates an error message when you compile the deployment unit.

finder-query element

finder-query defines the WebLogic Query Language (WLQL) expression used to query EJB objects from the RDBMS. WLQL uses a standard set of operators against finder parameters, EJB attributes, and Java language expressions. See Using WebLogic Query Language (WLQL) for more information on WLQL.

Note: Always define the text of the finder-query value using the XML CDATA attribute. Using CDATA ensures that any special characters in the WLQL string do not cause errors when the finder is compiled.

finder-expression stanza

You can use the optional finder-expression to embed a Java language expression within the WLQL expression. EJB providers can use this functionality to create dynamic finder methods in WLQL at deployment time. See Using Java Expressions in WLQL for more information.

Using WebLogic Query Language (WLQL)

In the weblogic-cmp-rdbms-jar.xml file, each finder-query stanza must include a WLQL string that defines the query used to return EJBs.

Syntax

WLQL strings use the prefix notation for comparison operators:

    (operator operand1 operand2)

Additional WLQL operators accept a single operand, a text string, or a keyword.

Operators

The following are valid WLQL operators:

####

Operator | Description | Sample Syntax
--- | --- | ---
= | Equals | (= operand1 operand2)
< | Less than | (< operand1 operand2)
> | Greater than | (> operand1 operand2)
<= | Less than or equal to | (<= operand1 operand2)
>= | Greater than or equal to | (>= operand1 operand2)
! | Boolean not | (! operand)
& | Boolean and | (& operand)
| | Boolean or | (| operand)
like | Wildcard search based on % symbol in the supplied text_string | (like `text_string%')
isNull | Value of single operand is null | (isNull operand)
isNotNull | Value of single operand is not null | (isNotNull operand)
orderBy | Order results using specified database colums Note: Always specify a database column name in the orderBy clause, rather than a persistent field name. WebLogic Server does not translate field names specified in orderBy. | (orderBy 'column_name')
desc | Orders results in descending order. Used only in combination with orderBy. | (orderBy 'column_name desc')

Operands

Valid WLQL operands include:

- another WLQL expression

- a container-managed field defined elsewhere in the weblogic-cmp-rdbms-jar.xml file

  Note: You cannot use RDBMS column names as operands in WLQL. Instead, use the EJB attribute (field) that maps to the RDBMS column, as defined in the attribute-map in weblogic-cmp-rdbms-jar.xml.

- A finder parameter or Java expression identified by $n, where n is the number of the parameter or expression. By default, $n maps to the nth parameter in the signature of the finder method. To write more advanced WLQL expressions that embed Java expressions, map $n to a Java expression as described in Using Java Expressions in WLQL.

  Note: The $n notation is based on an array that begins with 0, not 1. For example, the first three parameters of a finder correspond to $0, $1, and $2. Expressions need not map to individual parameters - advanced finders can define more expressions than parameters.

Examples

The following examples show excerpts from the weblogic-cmp-rdbms-jar.xml file that use basic WLQL expressions. You can also enter WLQL expressions using the EJB Deployer graphical interface, as described in Editing EJB finder method expressions.

See Using Java Expressions in WLQL for more advanced examples that embed Java expressions.

- This example returns all EJBs that have the balance attribute greater than the balanceGreaterThan parameter specified in the finder. The finder method signature in EJBHome is:

      public Enumeration findBigAccounts(double balanceGreaterThan)

            throws FinderException, RemoteException;

  The sample <finder> stanza is:

      <finder>

            <method-name>findBigAccounts</method-name>

            <method-params>

                 <method-param>double</method-param>

            </method-params>

            <finder-query><![CDATA[(> balance $0)]]></finder-query>

      </finder>

  Note that the balance field must be defined in the attribute map of the EJB's persistence deployment file.

  Note: Always define the text of the finder-query value using the XML CDATA attribute. Using CDATA ensures that any special characters in the WLQL string do not cause errors when the finder is compiled.

- The following example shows how to use compound WLQL expressions. Also note the use of single quotes (') to distinguish strings:

      <finder-query><![CDATA[(& (> balance $0) (! (= accountType 'checking')))]]></finder-query>

- The following example finds all the EJBs in a table. It uses the sample finder method signature:

      public Enumeration findAllAccounts()

            throws FinderException, RemoteException

  The sample <finder> stanza uses an empty WLQL string:

      <finder>

            <method-name>findAllAccounts</method-name>

            <finder-query></finder-query>

      </finder>

- The following query finds all EJBs whose lastName field starts with "M":

      <finder-query><![CDATA[(like lastName `M%')]]></finder-query>

- The following query is an example of using "like" with a string parameter:

      <finder-query><![CDATA[(like title $0)]]></finder-query>

- This query returns all EJBs that have a null firstName field:

      <finder-query><![CDATA[(isNull firstName)]]></finder-query>

- This query returns all EJBs whose balance field is greater than 5000, and orders the beans by the database column, id:

      <finder-query><![CDATA[(orderBy 'id' (> ))]]></finder-query>

- This query is similar to the previous example, except that the EJBs are returned in descending order:

      <finder-query><![CDATA[(orderBy 'id desc' (> ))]]></finder-query>

Using Java Expressions in WLQL

Notes: WebLogic Server supports embedded Java statements in WLQL for writing advanced finder capabilities. The basic WLQL functionality described in Using WebLogic Query Language (WLQL) provides capabilities that are necessary for most finders.

Future versions of the WebLogic Server EJB container will use the EJB QL query language (as required by the EJB 2.0 specification). EJB QL does not provide support for embedded Java expressions. Therefore, to ensure easier upgrades to future EJB containers, create entity EJB finders without embedding Java expressions in WLQL.

This section describes how to embed Java expressions into WLQL by editing XML elements directly in the deployment file. You can also use the EJB Deployer graphical interface to embed Java expressions, as described in Editing EJB finder method expressions.

In basic WLQL expressions, there is a one-to-one mapping between the parameters in the finder method signature and the expressions designated by the $n notation. For example, in the method signature:

    public Enumeration findSomeAccounts(double maxBal, String ownerID)

          throws FinderException, RemoteException

WLQL assigns $0 to the value of maxBal and $1 to the value of OwnerID by default. Using this default mapping, you can create finders such as:

    <finder>

          <method-name>findSomeAccounts</method-name>

          <method-params>

               <method-param>double</method-param>

               <method-param>java.lang.String</method-param>

          </method-params>

          <finder-query><![CDATA[(& (< balance $0) (= owner $1))]]></finder-query>

    </finder>

WLQL also enables EJB developers to embed Java expressions within WLQL expressions designated by $n. To use this feature, you must override the assignment of individual $n expressions using the finder-expression stanza in weblogic-cmp-rdbms-jar.xml.

The finder-expression stanza includes the following XML elements:

- expression-number identifies the number of the expression you want to override. The expression number must be unique among the expressions defined for a finder method. Expression numbers start at zero and continue in sequence up to the total number of expressions used in the finder.

- expression-text contains the full Java expression that will replace the $n expression number in the finder's WLQL string. Within the expression text, you can use the @n notation to refer to the nth parameter in the finder method signature. Expressions need not map to individual parameters - advanced finders can define more expressions than parameters.

  Note: Always define the value of expression-text using the XML CDATA attribute. Using CDATA ensures that the Java expression does not cause compilation errors when the finder is compiled.

- expression-type identifies the Java return type of the Java expression. The expression must produce a value that is compatible with the specified expression-type. If you are unsure of the exact type of the return value, specify an encompassing Java type (such as long when you expect that only an int is necessary).

  Note: If the generated Java expression is incompatible with the specified expression-type, ejbc displays a error when you compile the EJB code.

Example

The following example uses the finder method signature:

    public Enumeration findSomeAccounts(double maxBal, String ownerID)

          throws FinderException, RemoteException

By embedding a simple Java expression in the WLQL string, you can convert the supplied maxBal value to another currency before querying the RDBMS. For example, if maxBal is supplied in U.S. dollars and the conversion rate to pounds is 1.6483, you can use a simple expression to multiply the value:

    <finder>

      <method-name>findSomeAccounts</method-name>

      <method-params>

        <method-param>double</method-param>

        <method-param>java.lang.String</method-param>

      </method-params>

      <finder-query>(& (< balance $0) (= owner $1))</finder-query>

      <finder-expression>

        <expression-number>0</expression-number>

        <expression-text>@0 * 1.6483</expression-text>

        <expression-type>long</expression-type>

      </finder-expression>

    </finder>

In the above example, $0 is replaced by the Java expression @0 * 1.6483, which multiplies the value of maxBal by 1.6483. Because the EJB provider did not override the value of $1, WLQL maps $1 to the second parameter in the finder method signature, ownerID.

A more advanced version of this finder could use Java to determine the conversion rate when converting maxBal:

    ...

    <finder-expression>

          <expression-number>0</expression-number>

          <expression-text>@0 * Double.parseDouble(System.getProperties().get("rate.pounds.dollars"))</expression-text>

          <expression-type>long</expression-type>

    </finder-expression>

    ...

Restrictions

WebLogic Server does not parse or in any way validate the expression supplied in expression-text. The EJB provider must ensure that the expression is valid Java.

Any errors in the expression text will appear as compilation errors when you compile the EJB with ejbc.

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