Oracle8i CORBA Developer's Guide and Reference
Release 3 (8.1.7)

Part Number A83722-01

Library

Product

Contents

Index

Go to previous page Go to beginning of chapter Go to next page

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


Go to previous page
Go to beginning of chapter
Go to next page
Oracle
Copyright © 1996-2000, Oracle Corporation.

All Rights Reserved.

Library

Product

Contents

Index