Oracle8i CORBA Developer's Guide and Reference Release 3 (8.1.7) Part Number A83722-01 |
Library | Service | Contents | Index

## JTA Client-Side Demarcation

For JTA, client-side demarcated transactions are explicitly demarcated programmatically through the `UserTransaction` object, which must be bound with the `bindut` command into the namespace. With client-side transaction demarcation, the client controls the transaction. The client starts a global transaction by invoking the `UserTransaction begin` method; it ends the transaction by invoking either the `commit` or `rollback` methods.

In addition, the client must always set up an environment including a `Hashtable` with authentication information and namespace location URL. It must also register an `OracleDriver` when retrieving the transaction objects from the namespace.

Figure 7-3 shows a client invoking a server object. The client starts a global transaction, then invokes the object. The transactional context is propagated to include the server object.

#### Figure 7-3 Client Demarcated Global Transaction

The following must occur for the client to demarcate the transaction:

1. Initialize a `Hashtable` environment with the namespace address and authentication information.

2. Register the `OracleDriver`.

3. Retrieve the `UserTransaction` object from the namespace within the client logic. When you retrieve the `UserTransaction` object from any client, the URL must consist of "`jdbc_access://`" prefix before the JNDI name.

4. Start the global transaction within the client using `UserTransaction.begin()`.

5. Retrieve the server object.

6. Invoke any object methods to be included in the transaction.

7. End the transaction through `UserTransaction.commit()` or `UserTransaction.rollback()`.

Example 7-2 shows a client that invokes a server object within the transaction.

#### Example 7-2 Employee Client Code for Client Demarcated Transaction

After binding the `UserTransaction` object, your client code can retrieve the `UserTransaction` object and start a global transaction. Since the client is retrieving the `UserTransaction` object from a remote site, the lookup requires authentication information, location of the namespace, the `OracleDriver` registration, and the "`jdbc_access://`" prefix.

    import employee.*;
    import java.sql.DriverManager;
    import java.util.Hashtable;
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.transaction.UserTransaction;
    import java.sql.SQLException;
    import javax.naming.NamingException;
    import oracle.aurora.jndi.jdbc_access.jdbc_accessURLContextFactory;
    import oracle.aurora.jndi.sess_iiop.ServiceCtx;

    public class Client
    {
     public static void main (String[] args) throws Exception
     {
      UserTransaction ut = null;
      EmployeeInfo info;
      String sessiiopURL = args [0];
      String objectName = args [1];

      //Set up the service URL to where the UserTransaction object
      //is bound. Since from the client, the connection to the database
      //where the namespace is located can be communicated with over either
      //a Thin or OCI8 JDBC driver. This example uses a Thin JDBC driver.
      String namespaceURL = "jdbc:oracle:thin:@nsHost:1521:ORCL";

      // lookup usertransaction object in the namespace
      try {
        //1.(a) Authenticate to the database.
        // create InitialContext and initialize for authenticating client
        Hashtable env = new Hashtable ();
        env.put (Context.URL_PKG_PREFIXES, "oracle.aurora.jndi");
        env.put (Context.SECURITY_PRINCIPAL, "SCOTT");
        env.put (Context.SECURITY_CREDENTIALS, "TIGER");
        env.put (Context.SECURITY_AUTHENTICATION, ServiceCtx.NON_SSL_LOGIN);
        //1.(b) Specify the location of the namespace where the transaction objects
        //   are bound.
        env.put(jdbc_accessURLContextFactory.CONNECTION_URL_PROP, namespaceURL);
        Context ic = new InitialContext (env);

        //2. Register a JDBC OracleDriver. Required for JDBC connection to retrieve
        // UserTransaction from namespace.
        DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver());

        //3. Retrieve the UserTransaction object from JNDI namespace
        ut = (UserTransaction)ic.lookup ("jdbc_access://test/myUT");

        //4. Start the transaction
        ut.begin();

        //5. Retrieve the server object reference
        // lookup employee object in the namespace
        Employee employee = (Employee)ic.lookup

    	("sess_iiop://myhost:1521:orcl/test/employee");

        //6. Perform bean business logic.
        // retrieve the info
        info = employee.getEmployee ("SCOTT");
        System.out.println ("Before Update: " + info.name +"  " + info.salary);

        // change the salary and update it
        System.out.println ("Increase by 10%");
        info.salary += (info.salary * 10) / 100;
        employee.updateEmployee (info);

        //7. End the transaction
        //Commit the updated value
        ut.commit ();
    }

The transaction context is propagated to the object when the client invokes it.

#### JTA Client-Side Demarcation Including Databases

The previous example showed how a transaction context was propagated to server objects from a client within the JTA global transaction. When you execute the server object, the transaction is propagated over the IIOP transport layer. In addition to invoking IIOP server objects, you may wish to update databases over JDBC connections. The databases that the object accesses must be enlisted to be included within the global transaction.

If you access an Oracle8i database from the server that should be included in the transaction, you must open the connection to the database after the global transaction starts.

Note: At this time, the Oracle JTA implementation does not support including non-Oracle databases in a global transaction.

This section shows how you enlist databases using a JDBC connection in tandem with the IIOP server object propagation.

To include a remote database within the transaction from a client, you must use a `DataSource` object, which has been bound in the namespace as a JTA `DataSource`. Then, invoke the `getConnection` method of the `DataSource` object after the transaction has started, and the database is included in the global transaction.

The following must occur in the client runtime to demarcate the transaction:

1. Initialize a `Hashtable` environment with the namespace address and authentication information.

2. Register the `OracleDriver`.

3. Retrieve the `UserTransaction` object from the namespace within the client logic. When you retrieve the `UserTransaction` object from the client, the URL must consist of "`jdbc_access://`" prefix before the JNDI name.

4. Start the global transaction within the client using `UserTransaction.begin()`.

5. Enlist any database resources to be included in the transaction by opening a connection to the specified database, as follows:

   1. Retrieve the `DataSource` object from the namespace within the client logic. When you retrieve the `DataSource` object from any client, the URL must consist of "`jdbc_access://`" prefix before the JNDI name.

   2. Open a connection to the database through `DataSource.getConnection` method.

6. Retrieve the object reference.

7. Invoke any object methods to be included in the transaction.

8. Invoke SQL DML statements against any enlisted databases.

9. End the transaction through `UserTransaction.commit()` or `UserTransaction.rollback()`.

Example 7-3 shows a client that invokes a server object and enlists a single database within the transaction.

#### Example 7-3 Employee Client Code for Client Demarcated Transaction

Before starting the client, you must first bind the `UserTransaction` and `DataSource` objects in the namespace. The following example follows the steps listed in "JTA Client-Side Demarcation Including Databases".

    import employee.*;
    import java.sql.DriverManager;
    import java.util.Hashtable;
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.transaction.UserTransaction;
    import java.sql.SQLException;
    import javax.naming.NamingException;
    import oracle.aurora.jndi.jdbc_access.jdbc_accessURLContextFactory;
    import oracle.aurora.jndi.sess_iiop.ServiceCtx;

    public class Client
    {
     public static void main (String[] args) throws Exception
     {
      UserTransaction ut = null;
      EmployeeInfo info;
      String sessiiopURL = args [0];
      String objectName = args [1];
      String dsName = args [2];

      //Set up the service URL to where the UserTransaction object
      //is bound. Since from the client, the connection to the database
      //where the namespace is located can be communicated with over either
      //a Thin or OCI8 JDBC driver. This example uses a Thin JDBC driver.
      String namespaceURL = "jdbc:oracle:thin:@nsHost:1521:ORCL";

      // lookup usertransaction object in the namespace
      try {
        //1.(a) Authenticate to the database.
        // create InitialContext and initialize for authenticating client
        Hashtable env = new Hashtable ();
        env.put (Context.URL_PKG_PREFIXES, "oracle.aurora.jndi");
        env.put (Context.SECURITY_PRINCIPAL, "SCOTT");
        env.put (Context.SECURITY_CREDENTIALS, "TIGER");
        env.put (Context.SECURITY_AUTHENTICATION, ServiceCtx.NON_SSL_LOGIN);
        //1.(b) Specify the location of the namespace where the transaction objects
        //   are bound.
        env.put(jdbc_accessURLContextFactory.CONNECTION_URL_PROP, namespaceURL);
        Context ic = new InitialContext (env);

        //2. Register a JDBC OracleDriver. This is a requirement for retrieving
        // the UserTransaction and DataSource objects from the namespace over
        // a JDBC connection.
        DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver());

        //3. Retrieve the UserTransaction object from JNDI namespace
        ut = (UserTransaction)ic.lookup ("jdbc_access://test/myUT");

        //4. Start the transaction
        ut.begin();

        //5.(a) Retrieve the DataSource (that was previously bound with bindds in
        // the namespace. After retrieving the DataSource...
        // get a connection to a database. You need to provide authentication info
        // for a remote database lookup, similar to what you would do from a client.
        // In addition, if this was a two-phase commit transaction, you must provide
        // the username and password.
        DataSource ds = (DataSource)ic.lookup ("jdbc_access://test/empDB");

        //5.(b). Get connection to the database through DataSource.getConnection
        // in this case, the database requires the same username and password as
        // set in the environment.
        Connection conn = ds.getConnection ();

        //6. Retrieve the server object reference
        // lookup employee object in the namespace
        Employee employee = (Employee)ic.lookup (sessiiopURL + objectName);

        //7 (a). Perform bean business logic.
        // retrieve the info
        info = employee.getEmployee ("SCOTT");
        System.out.println ("Before Update: " + info.name +"  " + info.salary);

        // change the salary and update it
        System.out.println ("Increase by 10%");
        info.salary += (info.salary * 10) / 100;
        employee.updateEmployee (info);

        //7 (b). Execute SQL statements against the enlisted database.
        Statement stmt = conn.createStatement ();
        int cnt = stmt.executeUpdate ("insert into my_tab values (39304)");

        //8. Close the database connection.
        conn.close ();

        //9. End the transaction
        //Commit the updated value
        ut.commit ();
    }

| Copyright © 1996-2000, Oracle Corporation. All Rights Reserved. |
Library | Service | Contents | Index