External transaction managers
Typically, eXtreme Scale transactions begin with the Session.begin method and end with the Session.commit method. However, when an ObjectGrid is embedded, an external transaction coordinator can start and end transactions. In this case, you do not need to call the begin or commit methods.
External transaction coordination
The TransactionCallback plug-in is extended with the isExternalTransactionActive(Session session) method that associates the eXtreme Scale session with an external transaction. The method header follows:
public synchronized boolean isExternalTransactionActive(Session session)
For example, eXtreme Scale can be set up to integrate with WebSphere® Application Server and WebSphere Extended Deployment.
Also, eXtreme Scale provides a built in plug-in called the WebSphere Plug-ins for managing transaction life cycle events, which describes how to build the plug-in for WebSphere Application Server environments, but you can adapt the plug-in for other frameworks.
/**
* This method is required to associate an objectGrid session with a WebSphere
* Application Server transaction ID.
*/
Map/**/ localIdToSession;
public synchronized boolean isExternalTransactionActive(Session session)
{
// remember that this localid means this session is saved for later.
localIdToSession.put(new Integer(jta.getLocalId()), session);
return true;
}
Retrieve an external transaction
public J2EETransactionCallback() {
super();
localIdToSession = new HashMap();
String lookupName="java:comp/websphere/ExtendedJTATransaction";
try
{
InitialContext ic = new InitialContext();
jta = (ExtendedJTATransaction)ic.lookup(lookupName);
jta.registerSynchronizationCallback(this);
}
catch(NotSupportedException e)
{
throw new RuntimeException("Cannot register jta callback", e);
}
catch(NamingException e){
throw new RuntimeException("Cannot get transaction object");
}
}
For other products, you can use a similar approach to retrieve the transaction service object.
Control commit by external callback
public class J2EETransactionCallback implements
com.ibm.websphere.objectgrid.plugins.TransactionCallback, SynchronizationCallback {
public J2EETransactionCallback() {
super();
String lookupName="java:comp/websphere/ExtendedJTATransaction";
localIdToSession = new HashMap();
try {
InitialContext ic = new InitialContext();
jta = (ExtendedJTATransaction)ic.lookup(lookupName);
jta.registerSynchronizationCallback(this);
} catch(NotSupportedException e) {
throw new RuntimeException("Cannot register jta callback", e);
}
catch(NamingException e) {
throw new RuntimeException("Cannot get transaction object");
}
}
public synchronized void afterCompletion(int localId, byte[] arg1,boolean didCommit) {
Integer lid = new Integer(localId);
// find the Session for the localId
Session session = (Session)localIdToSession.get(lid);
if(session != null) {
try {
// if WebSphere Application Server is committed when
// hardening the transaction to backingMap.
// We already did a flush in beforeCompletion
if(didCommit) {
session.commit();
} else {
// otherwise rollback
session.rollback();
}
} catch(NoActiveTransactionException e) {
// impossible in theory
} catch(TransactionException e) {
// given that we already did a flush, this should not fail
} finally {
// always clear the session from the mapping map.
localIdToSession.remove(lid);
}
}
}
public synchronized void beforeCompletion(int localId, byte[] arg1) {
Session session = (Session)localIdToSession.get(new Integer(localId));
if(session != null) {
try {
session.flush();
} catch(TransactionException e) {
// WebSphere Application Server does not formally define
// a way to signal the
// transaction has failed so do this
throw new RuntimeException("Cache flush failed", e);
}
}
}
}
Use eXtreme Scale APIs with the TransactionCallback plug-in
Session ogSession = ...;
ObjectMap myMap = ogSession.getMap("MyMap");
ogSession.begin();
MyObject v = myMap.get("key");
v.setAttribute("newValue");
myMap.update("key", v);
ogSession.commit();
public void myMethod() {
UserTransaction tx = ...;
tx.begin();
Session ogSession = ...;
ObjectMap myMap = ogSession.getMap("MyMap");
yObject v = myMap.get("key");
v.setAttribute("newValue");
myMap.update("key", v);
tx.commit();
}
The myMethod method is similar to a Web application scenario. The application uses the normal UserTransaction interface to begin, commit, and roll back transactions. The eXtreme Scale automatically begins and commits around the container transaction. If the method is an Enterprise JavaBeans (EJB) method that uses the TX_REQUIRES attribute, then remove the UserTransaction reference and the calls to begin and commit transactions and the method works the same way. In this case, the container is responsible for starting and ending the transaction.