Gerenciadores de Transações Externas

Normalmente, as transações do eXtreme Scale começam com o método Session.begin e terminam com o método Session.commit. Entretanto, quando um ObjectGrid é integrado, um coordenador de transação externa pode iniciar e terminar transações. Nesse caso, você não precisa chamar os métodos begin ou commit.

Coordenação de Transação Externa

O plug-in TransactionCallback é estendido com o método isExternalTransactionActive(Session session) que associa a sessão do eXtreme Scale com uma transação externa. O cabeçalho do método é o seguinte:

public synchronized boolean isExternalTransactionActive(Session session)

Por exemplo, o eXtreme Scale pode ser configurado para se integrar com o WebSphere Application Server e WebSphere Extended Deployment.

Além disso, o eXtreme Scale oferece um plug-in integrado chamado WebSphere Plug-ins para o Gerenciamento de Eventos de Ciclo de Vida da Transação, que descreve como construir o plug-in para ambientes do WebSphere Application Server, e também adaptar o plug-in para outras estruturas.

A chave para esta integração total é a utilização da API ExtendedJTATransaction no WebSphere Application Server Versão 5.x e Versão 6.x. Porém, se você estiver usando o WebSphere Application Server Versão 6.0.2, aplique a APAR PK07848 para suportar este método. Use o código de amostra a seguir para associar uma sessão do ObjectGrid com um ID da transação do WebSphere Application Server:
/**
* This method is required to associate an objectGrid session with a WebSphere 
* Application Server transaction ID.
*/
Map/**/ localIdToSession;
public synchronized boolean isExternalTransactionActive(Session session)
{
    // lembre-se de que este localid significa que a sessão é salva posteriormente.
    localIdToSession.put(new Integer(jta.getLocalId()), session);
    return true;
}

Recuperar uma Transação Externa

Algumas vezes você pode precisar recuperar um objeto de serviço de transação externa para o plug-in TransactionCallback usar. No servidor do WebSphere Application Server, busque o objeto ExtendedJTATransaction de seu espaço de nomes como mostrado no exemplo a seguir:
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 outros produtos, é possível utilizar uma abordagem semelhante para recuperar o objeto de serviço de transações.

Controlar Confirmação por Retorno de Chamada Externo

O plug-in TransactionCallback precisa receber um sinal externo para confirmar ou recuperar a sessão do eXtreme Scale. Para receber este sinal externo, utilize o retorno de chamada do serviço de transações externas. Implemente a interface de retorno de chamada externa e registre-a no serviço de transações externas. Por exemplo, com WebSphere Application Server implemente a interface SynchronizationCallback como mostrado no exemplo a seguir:
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 as APIs do eXtreme Scale com o plug-in TransactionCallback

O plug-in TransactionCallback desativa a auto-consolidação no eXtreme Scale. O padrão de uso normal para um eXtreme Scale é o seguinte:
Session ogSession = ...;
ObjectMap myMap = ogSession.getMap("MyMap");
ogSession.begin();
MyObject v = myMap.get("key");
v.setAttribute("newValue");
myMap.update("key", v);
ogSession.commit();
Quando este plug-in TransactionCallback está em uso, o eXtreme Scale assume que o aplicativo usa o eXtreme Scale quando uma transação gerenciada pelo contêiner está presente. O trecho de código anterior muda o seguinte código neste ambiente:
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();
}

O método myMethod é semelhante a um cenário de aplicativo da Web. O aplicativo usa a interface UserTransaction normal para iniciar, consolidar e recuperar transações. O eXtreme Scale automaticam ente inicia e consolida a transação do contêiner. Se o método for um método EJB (Enterprise JavaBeans) que usa o atributo TX_REQUIRES, então remova a referência UserTransaction e as chamadas para iniciar e consolidar transações e o método funciona da mesma forma. Neste caso, o contêiner é responsável por iniciar e encerrar a transação.