Transactional Object using Resource

This example illustrates how a transaction object participates in a transaction. The transaction object implementation uses a simple resource as its storage. The SimpleResource object implements the resource methods to make it compliant with transaction services.

ServerA.java            // Server that hosts a Transactional object
test.idl                // IDL describing the SimpleResource and TestRes interfaces.
SimpleResourceImpl.java // Simple CORBA Resource implementation.
TestXAImpl.java         // Transactional object implementation using XA.

Compiling and Executing

Use the supplied ANT build 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

ServerA Implementation

This is a simple server program that activates the TestRes 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 transobjres;
                                                                           
import java.io.*;
import java.sql.*;
import java.util.*;
import javax.sql.*;
                                                                           
import javax.transaction.xa.XAResource;
import javax.transaction.TransactionManager;
                                                                           
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.jts.api.TransactionService;
import com.sssw.jbroker.api.transaction.TSIdentification;
                                                                           
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-RES");
    |                                                                      
    |   // Initialize the ORB and get instance of TM
    |   if (args.length > 0)
    |       System.setProperty("ORBPort", "55555");
    |   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 TestResImpl(ts, 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();
    |   |                                                                  
    |   |   TestRes test = TestResHelper.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));
    |   |   |   }
    |   |   }
    |   }
    }
}

Test IDL

The IDL describing the SimpleResource and TestRes interfaces.

#include "CosTransactions.idl"
                                                                           
module transobjres
{
        exception DidNotWork {};
                                                                           
        interface TestRes
        {
        |       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);
        };
                                                                           
        interface SimpleResource : CosTransactions::Resource
        {
        |       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);
        };
};

SimpleResource Implementation

This is a very simplistic implementation of the Resource interface. Its purpose is to illustrate how such objects can be used in distributed transactions.

package transobjres;
                                                                           
import java.sql.*;
import java.util.*;
                                                                           
import org.omg.CosTransactions.Vote;
import org.omg.CosTransactions.Current;
import org.omg.CosTransactions.Resource;
import org.omg.CosTransactions.NotPrepared;
import org.omg.CosTransactions.HeuristicMixed;
import org.omg.CosTransactions.HeuristicCommit;
import org.omg.CosTransactions.HeuristicHazard;
import org.omg.CosTransactions.HeuristicRollback;
                                                                           
import common.Utils;
import common.TestDataSource;
                                                                           
/*
 * This is very simple implementation of CORBA Resource.
 * It only keeps values in memory and does not do any
 * real storage.
 */
                                                                           
public class SimpleResourceImpl extends SimpleResourcePOA
{
    private String      _name;
    private Hashtable   _perm;
    private Hashtable   _temp;
    private boolean     _prepared;
                                                                           
    SimpleResourceImpl(String name) throws Exception
    {
    |   _name = name;
    |   _prepared = false;
    |   _perm = new Hashtable();
    |   _temp = new Hashtable();
    }
                                                                           
    public void insert(int key, int val)
    {
    |   _temp.put(new Integer(key), new Integer(val));
    }
                                                                           
    public int findv2(int key)
    {
    |   Integer val = (Integer)_temp.get(new Integer(key));
    |                                                                      
    |   if (val == null)
    |       val = (Integer)_perm.get(new Integer(key));
    |                                                                      
    |   if (val == null)
    |       return -1;
    |                                                                      
    |   return val.intValue();
    }
                                                                           
    public int remove(int keyval)
    {
    |   Integer key = new Integer(keyval);
    |   Integer val = (Integer)_temp.get(key);
    |                                                                      
    |   if (val != null) {
    |   |   _temp.remove(key);
    |   |   return 1;
    |   }
    |   return 0;
    }
                                                                           
    public Vote prepare()
        throws HeuristicMixed, HeuristicHazard
    {
    |   if (_prepared)
    |       throw new HeuristicHazard();
    |                                                                      
    |   for (Enumeration e = _temp.keys(); e.hasMoreElements() ;) {
    |   |   Object key = e.nextElement();
    |   |   _perm.put(key, _temp.get(key));
    |   }
    |   _prepared = true;
    |   System.out.println("+ SimpleResource "+_name+" prepare() -> VoteCommit");
    |   return Vote.VoteCommit;
    }
                                                                           
    public void rollback()
        throws HeuristicCommit, HeuristicMixed, HeuristicHazard
    {
    |   if (_prepared) {
    |   |   for (Enumeration e = _temp.keys(); e.hasMoreElements() ;) {
    |   |   |   Object key = e.nextElement();
    |   |   |   _perm.remove(key);
    |   |   }
    |   }
    |   _temp = new Hashtable();
    |   _prepared = false;
    |   System.out.println("+ SimpleResource "+_name+" rollback()");
    }
                                                                           
    public void commit()
        throws NotPrepared, HeuristicRollback, HeuristicMixed, HeuristicHazard
    {
    |   if (!_prepared)
    |       throw new NotPrepared();
    |                                                                      
    |   _temp = new Hashtable();
    |   _prepared = false;
    |   System.out.println("+ SimpleResource "+_name+" commit()");
    }
                                                                           
    public void commit_one_phase()
        throws HeuristicHazard
    {
    |   for (Enumeration e = _temp.keys(); e.hasMoreElements() ;) {
    |   |   Object key = e.nextElement();
    |   |   _perm.put(key, _temp.get(key));
    |   }
    |   _temp = new Hashtable();
    |   _prepared = false;
    |   System.out.println("+ SimpleResource "+_name+" commit-one-phase()");
    }
                                                                           
    public void forget()
    {
    }
}

Transactional Object Implementation

This is an implementation of an transactional object that uses the SimpleResource implementation as its storage.

package transobjres;
                                                                           
import java.sql.*;
import javax.sql.*;
import java.util.*;
                                                                           
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import javax.transaction.xa.XAResource;
                                                                           
import com.sssw.jts.api.TransactionService;
                                                                           
import org.omg.CORBA.ORB;
import org.omg.PortableServer.POA;
import org.omg.CosTransactions.Current;
                                                                           
public class TestResImpl extends TestResPOA
{
    Current             _current;
    SimpleResource      _simp_res;
    Hashtable           _regtrans;
                                                                           
    static int          _counter = 1;
                                                                           
    TestResImpl(TransactionService ts, POA rootPOA) throws Exception
    {
    |   _current   = ts.getTransactionCurrent();
    |   _simp_res  = (SimpleResource)rootPOA.servant_to_reference(
    |           new SimpleResourceImpl("Simple-"+_counter++));
    |   _regtrans  = new Hashtable();
    }
                                                                           
    private void init() throws Exception
    {
    }
                                                                           
    public void term()
    {
    }
                                                                           
    public void insert(int v1, int v2) throws DidNotWork
    {
    |   try 
    |   {
    |   |   init();
    |   |   String tran = _current.get_transaction_name();
    |   |   if (_regtrans.get(tran) == null) {
    |   |   |   _current.get_control().get_coordinator().register_resource(_simp_res);
    |   |   |   _regtrans.put(tran, tran);
    |   |   }
    |   |   System.out.println("+ Insert values("+v1+", "+v2+") into SimpleResource");
    |   |   _simp_res.insert(v1, v2);
    |   }
    |   catch (Exception ex)
    |   {
    |   |   ex.printStackTrace();
    |   |   throw new DidNotWork();
    |   }
    }
                                                                           
    public int findv2(int v1) throws DidNotWork
    {
    |   try 
    |   {
    |   |   init();
    |   |   return _simp_res.findv2(v1);
    |   }
    |   catch (Exception ex)
    |   {
    |   |   ex.printStackTrace();
    |   |   throw new DidNotWork();
    |   }
    }
                                                                           
    public int remove(int v1) throws DidNotWork
    {
    |   try 
    |   {
    |   |   init();
    |   |   return _simp_res.remove(v1);
    |   }
    |   catch (Exception ex)
    |   {
    |   |   ex.printStackTrace();
    |   |   throw new DidNotWork();
    |   }
    }
}


Copyright © 2003, 2004 Novell, Inc. All rights reserved. Copyright © 2001, 2002, 2003 SilverStream Software, LLC. All rights reserved.