Transactional Object using XA

This example illustrates how a transaction object participates in a transaction. The transaction object implementation uses XA enable database connection as its storage, and uses the JTA interfaces to perform its work transactionally.
ServerA.java            // Server that hosts a Transactional object
test.idl                // IDL describing the TestXA interface.
TestImpl.java           // Simple Transactional object implementation.

1 Compiling and Executing

Use the supplied ANT script to compile and execute the example programs. To compile run:
ant
To execute the test programs run:
ant test
To execute the test programs as a server run:
ant server

2 ServerA Implementation

This is a simple server program that activates the TestXA transactional object. In test mode it uses the object in several transactions which complete with rollback and commit. In server mode the object is activated and the server waits invocations from clients.
package transobjxa;
                                                                           
import java.io.*;
import java.sql.*;
import java.util.*;
                                                                           
import javax.sql.*;
                                                                           
import javax.transaction.TransactionManager;
import javax.transaction.xa.XAResource;
                                                                           
import org.omg.CORBA.Any;
import org.omg.CORBA.ORB;
import org.omg.CORBA.Policy;
import org.omg.CORBA.Object;
                                                                           
import org.omg.PortableServer.POA;
import org.omg.PortableServer.Servant;
import org.omg.PortableServer.ImplicitActivationPolicyValue;
                                                                           
import org.omg.CosTransactions.ADAPTS;
import org.omg.CosTransactions.SHARED;
import org.omg.CosTransactions.OTS_POLICY_TYPE;
import org.omg.CosTransactions.INVOCATION_POLICY_TYPE;
import org.omg.CosTransactions.Resource;
import org.omg.CosTransactions.TransactionFactory;
                                                                           
import com.sssw.jbroker.api.transaction.TSIdentification;
                                                                           
import com.sssw.jts.api.TransactionService;
                                                                           
import common.Utils;
import common.ResourceMapper;
import common.TestDataSource;
                                                                           
public class ServerA
{
    public static void main(String args[]) throws Exception
    {
    |   // Create a ResourceHandleMapper
    |   ResourceMapper resMapper = new ResourceMapper();
    |                                                                      
    |   System.setProperty("transaction.service.id", "EXAMPLE-TRANSOBJ-XA");
    |                                                                      
    |   // Initialize the ORB and get instance of TM
    |   if (args.length > 0)
    |       System.setProperty("ORBPort", "44444");
    |   ORB orb = ORB.init(args, null);
    |   TransactionService ts = (TransactionService)
    |       orb.resolve_initial_references("TransactionService");
    |                                                                      
    |   //
    |   // Recover TM with COLD Start.
    |   //
    |   ts.recover(resMapper, true, null);
    |                                                                      
    |   // get the root POA
    |   POA rootPOA = (POA) orb.resolve_initial_references("RootPOA");
    |                                                                      
    |   Servant servant = new TestXAImpl(ts, resMapper,
    |       TestDataSource._testDB1, TestDataSource._testTB1, rootPOA);
    |                                                                      
    |   // create a transactional POA
    |   Any otsPolicy = orb.create_any();
    |   otsPolicy.insert_short(ADAPTS.value);
    |   Any invPolicy = orb.create_any();
    |   invPolicy.insert_short(SHARED.value);
    |                                                                      
    |   POA txPOA = rootPOA.create_POA("txPOA",
    |       rootPOA.the_POAManager(),
    |       new Policy[] {
    |       |   rootPOA.create_implicit_activation_policy(
    |       |       ImplicitActivationPolicyValue.IMPLICIT_ACTIVATION),
    |       |   orb.create_policy(OTS_POLICY_TYPE.value, otsPolicy),
    |       |   orb.create_policy(INVOCATION_POLICY_TYPE.value, invPolicy)
    |       });
    |                                                                      
    |   // create a stringified object reference
    |   Object obj = txPOA.servant_to_reference(servant);
    |   String testIOR = orb.object_to_string(obj);
    |                                                                      
    |   if (args.length > 0) {
    |   |   // write the stringified object reference
    |   |   Utils.writeIOR(testIOR, "ior"); 
    |   |   System.out.println("+ Waiting for invocations ...");
    |   |   orb.run();
    |   |                                                                  
    |   } else {
    |   |                                                                  
    |   |   // activate the Root POA
    |   |   txPOA.the_POAManager().activate();
    |   |   rootPOA.the_POAManager().activate();
    |   |                                                                  
    |   |   TestXA test = TestXAHelper.narrow(obj);
    |   |                                                                  
    |   |   for (int i=1; i<=5; i++) {
    |   |   |   System.out.println();
    |   |   |   System.out.println("+ Start Transaction "+i);
    |   |   |   ts.getTransactionCurrent().begin();
    |   |   |   test.insert(i, 10+i);
    |   |   |   System.out.println("+ In Transaction Find("+i+") => "+(10+i)+" => "+test.findv2(i));
    |   |   |                                                              
    |   |   |   if ((i % 2) == 1) {
    |   |   |   |   ts.getTransactionCurrent().rollback();
    |   |   |   |   System.out.println("+ After Rollback Find("+i+") => -1 => "+test.findv2(i));
    |   |   |   } else {
    |   |   |   |   ts.getTransactionCurrent().commit(false);
    |   |   |   |   System.out.println("+ After Commit   Find("+i+") => "+(10+i)+" => "+test.findv2(i));
    |   |   |   }
    |   |   }
    |   }
    }
}

3 test IDL

The IDL describing the TestXA interface.
#include "CosTransactions.idl"
                                                                           
module transobjxa
{
        exception DidNotWork {};
                                                                           
        interface TestXA
        {
        |       void          insert(in unsigned long v1, in unsigned long v2) raises(DidNotWork);
        |       unsigned long findv2(in unsigned long v1) raises(DidNotWork);
        |       unsigned long remove(in unsigned long v1) raises(DidNotWork);
        };
};

4 Transactional Object Implementation

This is an implementation of an transactional object that uses XA and JTA interfaces to perform transactional operations. Using a database as its storage.
package transobjxa;
                                                                           
import java.sql.*;
import java.util.*;
                                                                           
import javax.sql.*;
                                                                           
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import javax.transaction.xa.XAResource;
                                                                           
import org.omg.CORBA.ORB;
import org.omg.PortableServer.POA;
import org.omg.CosTransactions.Current;
                                                                           
import com.sssw.jts.api.TransactionService;
                                                                           
import common.ResourceMapper;
import common.TestDataSource;
                                                                           
public class TestXAImpl extends TestXAPOA
{
    TransactionManager  _tm;
    Current             _current;
    ResourceMapper      _resMapper;
    String              _dbase;
    String              _table;
    TestDataSource      _xads;
    XAConnection        _xaconn;
                                                                           
    static int          _counter = 1;
                                                                           
    TestXAImpl(TransactionService ts, ResourceMapper rm,
        String dbase, String table, POA rootPOA) throws Exception
    {
    |   _tm        = ts.getTransactionManager();
    |   _current   = ts.getTransactionCurrent();
    |   _resMapper = rm;
    |   _dbase     = dbase;
    |   _table     = table;
    |   _xads      = null;
    |   _xaconn    = null;
    }
                                                                           
    private void init() throws Exception
    {
    |   if (_xads == null) {
    |   |   _xads = new TestDataSource(_dbase);
    |   |   createTable();
    |   }
    |                                                                      
    |   if (_xaconn == null)
    |       _xaconn = _xads.getXAConnection();
    }
                                                                           
    public void term()
    {
    |   try {_xaconn.close(); }catch(Exception e) {}
    }
                                                                           
    public void insert(int v1, int v2) throws DidNotWork
    {
    |   try 
    |   {
    |   |   init();
    |   |   XAResource  xares  = _xaconn.getXAResource();
    |   |   Connection  conn   = _xaconn.getConnection();
    |   |   _resMapper.addResource(xares);
    |   |                                                                  
    |   |   _tm.getTransaction().enlistResource(xares);
    |   |                                                                  
    |   |   System.out.println("+ Insert values("+v1+", "+v2+") into "+_dbase+" - "+_table);
    |   |   Statement stmt = conn.createStatement();
    |   |   stmt.execute("INSERT INTO "+_table+" (COL1, COL2) VALUES ("+v1+", "+v2+")");
    |   |   stmt.close();
    |   |                                                                  
    |   |   _tm.getTransaction().delistResource(xares, XAResource.TMSUSPEND);
    |   |                                                                  
    |   |   conn.close();
    |   }
    |   catch (Exception ex)
    |   {
    |   |   ex.printStackTrace();
    |   |   throw new DidNotWork();
    |   }
    }
                                                                           
    public int findv2(int v1) throws DidNotWork
    {
    |   try 
    |   {
    |   |   init();
    |   |   int         rval = -1;
    |   |   Transaction trans = _tm.getTransaction();
    |   |   XAResource  xares = null;
    |   |   Connection  conn;
    |   |                                                                  
    |   |   if (trans != null) {
    |   |   |   xares = _xaconn.getXAResource();
    |   |   |   conn  = _xaconn.getConnection();
    |   |   |   trans.enlistResource(xares);
    |   |   } else {
    |   |   |   xares = null;
    |   |   |   conn  = _xads.getConnection();
    |   |   }
    |   |                                                                  
    |   |   Statement   stmt = conn.createStatement();
    |   |   ResultSet   rset = stmt.executeQuery("SELECT COL2 FROM "+_table+" WHERE COL1="+v1);
    |   |                                                                  
    |   |   if (rset.next())
    |   |   {
    |   |   |   rval = rset.getInt(1);
    |   |   }
    |   |   rset.close();
    |   |   stmt.close();
    |   |   conn.close();
    |   |                                                                  
    |   |   if (trans != null) {
    |   |   |   trans.delistResource(xares, XAResource.TMSUSPEND);
    |   |   }
    |   |                                                                  
    |   |   return rval;
    |   }
    |   catch (Exception ex)
    |   {
    |   |   ex.printStackTrace();
    |   |   throw new DidNotWork();
    |   }
    }
                                                                           
    public int remove(int v1) throws DidNotWork
    {
    |   int nrows = 0;
    |   try 
    |   {
    |   |   init();
    |   |   int         rval = -1;
    |   |   Connection  conn = _xads.getConnection();
    |   |   Statement   stmt = conn.createStatement();
    |   |   nrows = stmt.executeUpdate("DELETE FROM "+_table+" WHERE COL1="+v1);
    |   |                                                                  
    |   |   stmt.close();
    |   |   conn.close();
    |   }
    |   catch (Exception ex)
    |   {
    |   |   ex.printStackTrace();
    |   |   throw new DidNotWork();
    |   }
    |   return nrows;
    }
                                                                           
    //
    // Create test table
    //
    void createTable() throws Exception
    {
    |   Connection  conn = null;
    |   Statement   stmt = null;
    |   try 
    |   {
    |   |   conn = _xads.getConnection();            
    |   |   stmt = conn.createStatement();
    |   |   try
    |   |   {
    |   |   |   int nrow = stmt.executeUpdate("DELETE FROM "+_table);
    |   |   |   System.out.println("+ Deleted "+nrow+" rows from table "+_dbase+"."+_table);
    |   |   }
    |   |   catch (SQLException ex)
    |   |   {
    |   |   |   System.out.println("+ Creating table "+_dbase+"."+_table+" ... ");
    |   |   |   stmt.execute("CREATE TABLE "+_table+"(COL1 INTEGER, COL2 INTEGER)");
    |   |   }
    |   }
    |   finally
    |   {
    |   |   if (stmt != null) { try { stmt.close(); } catch (Exception ex) {} }
    |   |   if (conn != null) { try { conn.close(); } catch (Exception ex) {} }
    |   }
    }
                                                                           
}
Copyright © 2000-2003, Novell, Inc. All rights reserved.