Normalmente, las transacciones eXtreme Scale empiezan con el método Session.begin y finalizan con el método Session.commit. Sin embargo, cuando se incorpora un ObjectGrid, un coordinador de transacciones externas puede iniciar y finalizar transacciones. En este caso, no es necesario llamar a los métodos begin o commit.
El plug-in TransactionCallback se amplía con el método isExternalTransactionActive(Session session) que asocia la sesión de eXtreme Scale con una transacción externa. La cabecera del método es la siguiente:
public synchronized boolean isExternalTransactionActive(Session session)
Por ejemplo, eXtreme Scale se puede configurar para integrarse con WebSphere Application Server y WebSphere Extended Deployment.
Además, eXtreme Scale proporciona un plug-in incorporado llamado WebSphere Plug-ins para gestionar los sucesos del ciclo de vida de transacciones, que describe cómo generar el plug-in para los entornos de WebSphere Application Server, pero puede adaptar el plug-in para otras infraestructuras.
/**
* Este método es necesario para asociar una sesión de objectGrid con un ID de
* transacción de WebSphere Application Server.
*/
Map/**/ localIdToSession;
public synchronized boolean isExternalTransactionActive(Session session)
{
// recuerde que este localid significa que la sesión se ha guardado para
ser utilizada más tarde.
localIdToSession.put(new Integer(jta.getLocalId()), session);
return true;
}
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");
}
}
Para otros productos, puede utilizar un acercamiento similar para recuperar el objeto de servicio de transacción.
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);
// buscar localId de Session
Session session = (Session)localIdToSession.get(lid);
if(session != null) {
try {
// si WebSphere Application Server se confirma al
// proteger la transacción para backingMap.
// Se realizó un vaciado en beforeCompletion
if(didCommit) {
session.commit();
} else {
// de lo contrario, retrotraer
session.rollback();
}
} catch(NoActiveTransactionException e) {
// imposible en teoría
} catch(TransactionException e) {
// como ya se ha hecho un vaciado, no debería producirse error
} finally {
// siempre borra la sesión de la correlación
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 no define formalmente
// una manera de indicar que la
// transacción ha fallado, por lo que debe hacer esto
throw new RuntimeException("Cache flush failed", e);
}
}
}
}
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();
}
El método myMethod es similar a un escenario de aplicación web. La aplicación utiliza la interfaz UserTransaction normal para empezar, confirmar y retrotraer transacciones. eXtreme Scale se inicia y se confirma automáticamente cerca de la transacción de contenedor. Si el método es un método EJB (Enterprise JavaBeans) que utiliza el atributo TX_REQUIRES, elimine la referencia de UserTransaction y las llamadas para iniciar y confirmar transacciones y el método funcionan del mismo modo. En este caso, el contenedor es responsable de iniciar y terminar la transacción.