bea.com | products | dev2dev | support | askBEA

Download Docs | Site Map | Glossary
Search

Configuring and Using WebLogic jDriver for Oracle

Using WebLogic jDriver for Oracle/XA in Distributed Transactions

The following sections describe how to integrate transactions with EJB and RMI applications that use the WebLogic jDriver for Oracle/XA and run under BEA WebLogic Server.

- Differences Using the WebLogic jDriver for Oracle in XA versus Non-XA Mode

- Configuring JDBC XA and Non-XA Resources

- Limitations of the WebLogic jDriver for Oracle XA

- Implementing Distributed Transactions

Differences Using the WebLogic jDriver for Oracle in XA versus Non-XA Mode

WebLogic jDriver for Oracle fully supports the JDBC 2.0 Optional Package API for distributed transactions. Applications using the driver in distributed transaction (XA) mode can use all JDBC 2.0 Core API the same way as in local transaction (non-XA) mode, with the exception of the following:

- Connections have to be obtained via the JDBC 2.0 javax.sql.DataSource API, but not through the deprecated java.sql.DriverManager or java.sql.Driver API.

- Physical database connections in a connection pool are handled differently. See Connection Behavior with the WebLogic XA jDriver.

- When used in WebLogic Server, you must configure a TxDataSource in order to use it. Refer to "Managing JDBC Connectivity" in the Administration Guide for instructions about configuring TxDataSource and Connection Pools.

- Auto commit is false by default. Attempting to enable autocommit mode by calling the java.sql.Connection.setAutoCommit method on the Connection will throw a SQLException.

- Attempting to complete the distributed transaction by calling java.sql.Connection.commit or java.sql.Connection.rollback methods will throw a SQLException.

The reason for the last two differences is because when the WebLogic jDriver for Oracle/XA participates in a distributed transaction, it is the external Transaction Manager that is demarcating and coordinating the distributed transaction.

For more information, refer to the JDBC 2.0 Standard Extension API spec [version 1.0, dated 98/12/7 Section 7.1 last 2 paragraphs].

Connection Behavior with the WebLogic XA jDriver

Because the WebLogic XA jDriver for Oracle internally uses the Oracle C/XA switch, xa_open and xa_start must be called on each thread that makes SQL calls. Also, the xa_open call creates a new physical XA database connection. To manage these restrictions, the WebLogic XA jDriver for Oracle does not create physical database connections until a thread attempts to use a connection. When a thread attempts to use a connection, the XA jDriver calls xa_open (and xa_start) to create the connection and associate it with the thread. After the database connection is created, the connection remains associated with the thread; the driver does not call xa_close. When the thread subsequently needs a database connection, it uses the same database connection associated with it, even though it appears to get and return a connection from the JDBC connection pool.

This driver behavior causes some changes in JDBC connection pool behavior:

- Physical database connections are not created when the connection pool is deployed (when created or at server startup), although logical JDBC connection objects are created.

- The number of logical connections in the connection pool most likely will not equal the number of physical database connections. The number of physical database connections will equal the number of execute threads from which SQL calls are made.

- The number of logical connection objects in the JDBC connection pool will limit the number of threads that can concurrently do database work. You should set the maximum capacity of the connection pool to the number of execute threads in your system.

- Physical database connections are not closed when the JDBC connection pool is destroyed (undeployed or on server shutdown). After the server is shutdown or after the JDBC connection pool is destroyed, physical database connections remain on the database and are eventually cleaned up by the DBMS.

Note: Note that these behavior changes apply only to JDBC connection pools that use the WebLogic XA jDriver to create physical database connections. They do not apply to connection pools that use other XA drivers.

Configuring JDBC XA and Non-XA Resources

You use the Administration Console to configure your JDBC resources, as described in the following sections.

JDBC/XA Resources

To allow XA JDBC drivers to participate in distributed transactions, configure the JDBC connection pool as follows:

- Specify the DriverName property as the name of the class supporting the javax.sql.XADataSource interface. That is, use weblogic.jdbc.oci.xa.XADataSource as the DriverName property (Driver Classname in the Administration Console).

- Ensure that the database properties are specified. For more information on data source properties for the WebLogic jDriver for Oracle, see Configuring XA JDBC Drivers for Distributed Transactions in the Administration Guide.

See the Administration Console Online Help on the JDBC Connection Pools panel for procedures and attribute definitions.

Non-XA JDBC Resources

To support non-XA JDBC resources, select the enableTwoPhaseCommit database property (Emulate Two-Phase Commit for non-XA Driver in the Administration Console) when configuring a JDBC Tx Data Source. For more information on this property, see Configuring Non-XA JDBC Drivers for Distributed Transactions in the Administration Guide.

Limitations of the WebLogic jDriver for Oracle XA

WebLogic jDriver for Oracle in XA mode does not support the following:

- Mixing local and global transactions. This throws a SQLException if an SQL operation is attempted with no global transaction.

- Performing DDL operations (e.g. create/drop table, stored procedures, and so forth). If you want to perform DDL operations, you need to define two different connection pools as follows:

  - One non-XA connection pool that can be used for DDL operations.

  - One XA connection pool that can be used for DML operations in distributed transactions.

- Setting the transaction isolation level for a transaction. Transactions use the transaction isolation level set on the connection or the default transaction isolation level for the database.

Implementing Distributed Transactions

This topic includes the following sections:

- Importing Packages

- Finding the Data Source via JNDI

- Performing a Distributed Transaction

Importing Packages

Listing 4-1 shows the packages that the application imports. In particular, note that:

- The java.sql.* and javax.sql.* packages are required for database operations.

- The javax.naming.* package is required for performing a JNDI lookup on the pool name, which is passed in as a command-line parameter upon server startup. The pool name must be registered on that server group.

Listing 4-1 Importing Required Packages

>     import java.sql.*;
>     import javax.sql.*;
>     import javax.naming.*;

Finding the Data Source via JNDI

Listing 4-2 shows how to find the data source via JNDI.

Listing 4-2 Finding the Data Source via JNDI

>     static DataSource pool;

>     ...

>     public void get_connpool(String pool_name)
>         throws Exception
>       {
>         try {
>           javax.naming.Context ctx = new InitialContext();
>           pool = (DataSource)ctx.lookup("jdbc/" + pool_name);
>         }
>         catch (javax.naming.NamingException ex){
>           TP.userlog("Couldn't obtain JDBC connection pool: " + pool_name);
>           throw ex;
>         }
>       }
>     }

Performing a Distributed Transaction

Listing 4-3 shows a distributed transaction involving two database connections and implemented as a business method within a session bean.

Listing 4-3 Performing a Distributed Transaction

>     public class myEJB implements SessionBean {
>          EJBContext ejbContext;

>          public void myMethod(...) {
>               javax,transaction.UserTransaction usertx;
>               javax.sql.DataSource data1;
>               javax.sql.DataSource data2;
>               java.sql.Connection conn1;
>               java.sql.Connection conn2;
>               java.sql.Statement stat1;
>               java.sql.Statement stat2;

>               InitialContext initCtx = new InitialContext();

>               //
>               // Initialize a user transaction object.
>               //
>               usertx = ejbContext.getUserTransaction();

>               //Start a new user transaction.
>               usertx.begin();

>               // Establish a connection with the first database
>               // and prepare it for handling a transaction.
>               data1 = (javax.sql.DataSource)
>                    initCtx.lookup("java:comp/env/jdbc/DataBase1");
>               conn1 = data1.getConnection();

>               stat1 = conn1.getStatement();

>               // Establish a connection with the second database
>               // and prepare it for handling a transaction.
>               data2 = (javax.sql.DataSource)
>                    initCtx.lookup("java:comp/env/jdbc/DataBase2");
>               conn2 = data1.getConnection();

>               stat2 = conn2.getStatement();

>               //Update both conn1 and conn2. The EJB Container
>               //automatically enlists the participating resources.
>               stat1.executeQuery(...);
>               stat1.executeUpdate(...);
>               stat2.executeQuery(...);
>               stat2.executeUpdate(...);
>               stat1.executeUpdate(...);
>               stat2.executeUpdate(...);

>               //Commit the transaction (apply the changes to the
>               //participating databases).
>               usertx.commit();

>               //Release all connections and statements.
>               stat1.close();
>               stat2.close();
>               conn1.close();
>               conn2.close();
>          }
>          ...
>      }