[Java programming language only]

Developing eXtreme Scale client components to use transactions

The WebSphere® eXtreme Scale resource adapter provides client connection management and local transaction support. With this support, Java™ Platform, Enterprise Edition (Java EE) applications can look up eXtreme Scale client connections and demarcate local transactions with Java EE local transactions or the eXtreme Scale APIs.

Before you begin

Create an eXtreme Scale connection factory resource reference.

About this task

There are several options for working with eXtreme Scale data access APIs. In all cases, the eXtreme Scale connection factory must be injected into the application component, or looked up in Java Naming Directory Interface (JNDI). After the connection factory is looked up, you can demarcate transactions and create connections to access the eXtreme Scale APIs.

You can optionally cast the javax.resource.cci.ConnectionFactory instance to a com.ibm.websphere.xs.ra.XSConnectionFactory that provides additional options for retrieving connection handles. The resulting connection handles must be cast to the com.ibm.websphere.xs.ra.XSConnection interface, which provides the getSession method. The getSession method returns a com.ibm.websphere.objectgrid.Session object handle that allows applications to use any of the eXtreme Scale data access APIs, such as the ObjectMap API and EntityManager API.

The Session handle and any derived objects are valid for the life of the XSConnection handle.

The following procedures can be used to demarcate eXtreme Scale transactions. You cannot mix each of the procedures. For example, you cannot mix global transaction demarcation and local transaction demarcation in the same application component context.

Procedure

  • Use autocommit, local transactions.
    Use the following steps to automatically commit data access operations or operations that do not support an active transaction:
    1. Retrieve a com.ibm.websphere.xs.ra.XSConnection connection outside of the context of a global transaction.
    2. Retrieve and use the com.ibm.websphere.objectgrid.Session session to interact with the data grid.
    3. Invoke any data access operation that supports autocommit transactions.
    4. Close the connection.
  • Use an ObjectGrid session to demarcate a local transaction.
    Use the following steps to demarcate an ObjectGrid transaction using the Session object:
    1. Retrieve a com.ibm.websphere.xs.ra.XSConnection connection.
    2. Retrieve the com.ibm.websphere.objectgrid.Session session.
    3. Use the Session.begin() method to start the transaction.
    4. Use the session to interact with the data grid.
    5. Use the Session.commit() or rollback() methods to end the transaction.
    6. Close the connection.
  • Use a javax.resource.cci.LocalTransction transaction to demarcate a local transaction.
    Use the following steps to demarcate an ObjectGrid transaction using the javax.resource.cci.LocalTransaction interface:
    1. Retrieve a com.ibm.websphere.xs.ra.XSConnection connection.
    2. Retrieve the javax.resource.cci.LocalTransaction transaction using the XSConnection.getLocalTransaction() method.
    3. Use the LocalTransaction.begin() method to start the transaction.
    4. Retrieve and use the com.ibm.websphere.objectgrid.Session session to interact with the data grid.
    5. Use the LocalTransaction.commit() or rollback() methods to end the transaction.
    6. Close the connection.
  • Enlist the connection in a global transaction.
    This procedure also applies to container-managed transactions:
    1. Begin the global transaction through the javax.transaction.UserTransaction interface or with a container-managed transaction.
    2. Retrieve a com.ibm.websphere.xs.ra.XSConnection connection.
    3. Retrieve and use the com.ibm.websphere.objectgrid.Session session.
    4. Close the connection.
    5. Commit or roll back the global transaction.
  • [Version 8.6 and later]Configure a connection to write multiple partitions in a transaction.
    Use the following steps to demarcate an ObjectGrid transaction using the Session object:
    1. Create a new com.ibm.websphere.xs.ra.XSConnectionSpec object.
    2. Call the XSConnectionSpec method and the setMultiPartitionSupportEnabled method with an argument of true.
    3. Retrieve the com.ibm.websphere.xs.ra.XSConnection connection to pass the XSConnectionSpec to the ConnectionFactory.getConnection method.
    4. Retrieve and use the com.ibm.websphere.objectgrid.Session session.

Example

See the following code example, which demonstrates the previous steps for demarcating eXtreme Scale transactions.
    // (C) Copyright IBM Corp. 2001, 2012.
    // All Rights Reserved. Licensed Materials - Property of IBM.
    package com.ibm.ws.xs.ra.test.ee;
     
    import javax.naming.InitialContext;
    import javax.resource.cci.Connection;
    import javax.resource.cci.ConnectionFactory;
    import javax.resource.cci.LocalTransaction;
    import javax.transaction.Status;
    import javax.transaction.UserTransaction;
     
    import junit.framework.TestCase;
     
    import com.ibm.websphere.objectgrid.ObjectMap;
    import com.ibm.websphere.objectgrid.Session;
    import com.ibm.websphere.xs.ra.XSConnection;
     
    /**
    * This sample requires that it runs in a J2EE context in your
    * application server. For example, using the JUnitEE framework servlet.
    *
    * The code in these test methods would typically reside in your own servlet,
    * EJB, or other web component.
    *
    * The sample depends on a configured WebSphere eXtreme Scale connection
    * factory registered at of JNDI Name of "eis/embedded/wxscf" that defines
    * a connection to a grid containing a Map with the name "Map1".
    *
    * The sample does a direct lookup of the JNDI name and does not require
    * resource injection.
    */
    public class DocSampleTests extends TestCase {
        public final static String CF_JNDI_NAME = "eis/embedded/wxscf";
        public final static String MAP_NAME = "Map1";
       
        Long                key = null;
        Long                value = null;
        InitialContext      ctx = null;
        ConnectionFactory   cf = null;
       
        public DocSampleTests() {
        }
        public DocSampleTests(String name) {
            super(name);
        }
        protected void setUp() throws Exception {
            ctx = new InitialContext();
            cf = (ConnectionFactory)ctx.lookup(CF_JNDI_NAME);
            key = System.nanoTime();
            value = System.nanoTime();
        }
        /**
         * This example runs when not in the context of a global transaction
         * and uses autocommit.
         */
        public void testLocalAutocommit() throws Exception {
            Connection conn = cf.getConnection();
            try {
                Session    session = ((XSConnection)conn).getSession();
                ObjectMap  map = session.getMap(MAP_NAME);
                map.insert(key, value); // Or various data access operations
            }
            finally {
                conn.close();
            }
        }
     
        /**
         * This example runs when not in the context of a global transaction
         * and demarcates the transaction using session.begin()/session.commit()
         */
        public void testLocalSessionTransaction() throws Exception {
            Session    session = null;
            Connection conn = cf.getConnection();
            try {
                session = ((XSConnection)conn).getSession();
                session.begin();
                ObjectMap  map = session.getMap(MAP_NAME);
                map.insert(key, value); // Or various data access operations
                session.commit();
            }
            finally {
                if (session != null && session.isTransactionActive()) {
                    try { session.rollback(); }
                    catch (Exception e) { e.printStackTrace(); }
                }
                conn.close();
            }
        }
       
        /**
         * This example uses the LocalTransaction interface to demarcate
         * transactions.
         */
        public void testLocalTranTransaction() throws Exception {
            LocalTransaction tx = null;
            Connection conn = cf.getConnection();
            try {
                tx = conn.getLocalTransaction();
                tx.begin();
                Session    session = ((XSConnection)conn).getSession();
                ObjectMap  map = session.getMap(MAP_NAME);
                map.insert(key, value); // Or various data access operations
                tx.commit(); tx = null;
            }
            finally {
                if (tx != null) {
                    try { tx.rollback(); }
                    catch (Exception e) { e.printStackTrace(); }
                }
                conn.close();
            }
        }
       
        /**
         * This example depends on an externally managed transaction,
         * the externally managed transaction might typically be present in
         * an EJB with its transaction attributes set to REQUIRED or REQUIRES_NEW.
         * NOTE: If there is NO global transaction active, this example runs in auto-commit
         *       mode because it doesn't verify a transaction exists.
         */
        public void testGlobalTransactionContainerManaged() throws Exception {
            Connection      conn = cf.getConnection();
            try {
                Session    session = ((XSConnection)conn).getSession();
                ObjectMap  map = session.getMap(MAP_NAME);
                map.insert(key, value); // Or various data access operations
            }
            catch (Throwable t) {
                t.printStackTrace();
                UserTransaction tx = (UserTransaction)ctx.lookup("java:comp/UserTransaction");
                if (tx.getStatus() != Status.STATUS_NO_TRANSACTION) {
                    tx.setRollbackOnly();
                }
            }
            finally {
                conn.close();
            }
        }
       
        /**
         * This example demonstrates starting a new global transaction using the
         * UserTransaction interface. Typically the container starts the global
         * transaction (for example in an EJB with a transaction attribute of
         * REQUIRES_NEW), but this sample will also start the global transaction
         * using the UserTransaction API if it is not currently active.
         */
        public void testGlobalTransactionTestManaged() throws Exception {
            boolean         started = false;
            UserTransaction tx = (UserTransaction)ctx.lookup("java:comp/UserTransaction");
            if (tx.getStatus() == Status.STATUS_NO_TRANSACTION) {
                tx.begin();
                started = true;
            }
            // else { called with an externally/container managed transaction }
            Connection      conn = null;
            try {
                conn = cf.getConnection(); // Get connection after the global tran starts
                Session    session = ((XSConnection)conn).getSession();
                ObjectMap  map = session.getMap(MAP_NAME);
                map.insert(key, value); // Or various data access operations
                if (started) {
                    tx.commit(); started = false; tx = null;
                }
            }
            finally {
                if (started) {
                    try { tx.rollback(); }
                    catch (Exception e) { e.printStackTrace(); }
                }
                if (conn != null) { conn.close(); }   
            }
        }
 /**
         /**
         * This example demonstrates a multi-partition transaction.
         */				
			
				public void testGlobalTransactionTestManagedMultiPartition() throws Exception {
						boolean started = false;
						XSConnectionSpec connSpec = new XSConnectionSpec();
						connSpec.setWriteToMultiplePartitions(true);
						UserTransaction tx = (UserTransaction)ctx.lookup("java:comp/UserTransaction");
						if (tx.getStatus() == Status.STATUS_NO_TRANSACTION) {
								tx.begin();
						started = true;
					}
				// else { called with an externally/container managed transaction }
						Connection conn = null;
									try {
						conn = cf.getConnection(connSpec); // Get connection after the global tran starts
						Session session = ((XSConnection)conn).getSession();
						ObjectMap map = session.getMap(MAP_NAME);
						map.insert(key, value); // Or various data access operations
						if (started) {
								tx.commit(); started = false; tx = null;
								}
						}
						finally {
							if (started) {
									try { tx.rollback(); }
									catch (Exception e) { e.printStackTrace(); }
							}
							if (conn != null) { conn.close(); }
						}
					}