Externe Transaktionsmanager

Gewöhnlich beginnen eXtreme-Scale-Transaktionen mit der Methode "Session.begin" und enden mit der Methode "Session.commit". Wenn jedoch ein ObjectGrid integriert ist, können Transaktionen von einem externen Transaktionskoordinator gestartet und beendet werden. In diesem Fall müssen Sie die Methode begin bzw. commit nicht aufrufen.

Externe Transaktionskoordination

Das TransactionCallback-Plug-in wurde mit der Methode "isExternalTransactionActive(Session session)" erweitert, die die eXtreme-Scale-Sitzung einer externen Transaktion zuordnet. Der Methodenheader sieht wie folgt aus:

public synchronized boolean isExternalTransactionActive(Session session)

eXtreme Scale kann beispielsweise für die Integration mit WebSphere Application Server und WebSphere Extended Deployment konfiguriert werden.

Außerdem stellt eXtreme Scale ein integriertes WebSphere-Plug-in bereit. Im Abschnitt Plug-ins für die Verwaltung von Ereignissen im Lebenszyklus von Transaktionen wird beschrieben, wie Sie das Plug-in für Umgebungen mit WebSphere Application Server erstellen, aber Sie können das Plug-in auch für andere Frameworks anpassen.

Der Schlüssel zu dieser nahtlosen Integration ist die Nutzung der API "ExtendedJTATransaction" in WebSphere Application Server Version 5.x und Version 6.x. Wenn Sie jedoch WebSphere Application Server Version 6.0.2 verwenden, müssen Sie für die Unterstützung dieser Methode APAR PK07848 anwenden. Verwenden Sie den folgenden Beispielcode, um einer ObjectGrid-Sitzung eine Transaktions-ID von WebSphere Application Server zuzuordnen:
/**
* Diese Methode ist erforderlich, um einer ObjectGrid-Sitzung eine Transaktions-ID von
* WebSphere Application Server zuzuordnen.
*/
Map/**/ localIdToSession;
public synchronized boolean isExternalTransactionActive(Session session)
{
    // Denken Sie daran, dass localid bedeutet, dass die Sitzung für spätere Verwendung gespeichert wird
    localIdToSession.put(new Integer(jta.getLocalId()), session);
    return true;
}

Externe Transaktion abrufen

Manchmal müssen Sie ein externes Transaktionsserviceobjekt für das TransactionCallback-Plug-in abrufen. Suchen Sie im Server von WebSphere Application Server das ExtendedJTATransaction-Objekt über den zugehörigen Namespace, wie im folgenden Beispiel gezeigt wird:
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");
    }
}

Für andere Produkte können Sie einen ähnlichen Ansatz verwenden, um das Transaktionsserviceobjekt abzurufen.

Festschreibung durch externen Callback steuern

Das TransactionCallback-Plug-in muss ein externes Signal empfangen, um die eXtreme-Scale-Sitzung festzuschreiben (Commit) oder rückgängig zu machen (Rollback). Zum Empfangen dieses externen Signals verwenden Sie den Callback des externen Transaktionsservice. Implementieren Sie die Schnittstelle für externe Callbacks, und registrieren Sie sie beim externen Transaktionsservice. Implementieren Sie beispielsweise für WebSphere Application Server die Schnittstelle "SynchronizationCallback", wie im folgenden Beispiel gezeigt wird:
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);
      // Session-Objekt für localId suchen
      Session session = (Session)localIdToSession.get(lid);
      if(session != null) {
         	try {
                        // Wenn WebSphere Application Server beim
            // Abschotten der Transaktion in der BackingMap festgeschrieben wird
            // Flush wurde bereits in beforeCompletion durchgeführt
            if(didCommit) {
               session.commit();
            } else {
               // otherwise rollback
               session.rollback();
            }
         } catch(NoActiveTransactionException e) {
            // In der Theorie nicht möglich
         } catch(TransactionException e) {
            // da bereits ein Flush durchgeführt wurde, sollte dies nicht fehlschlagen
         } finally {
            // Sitzung immer aus der Zuordnungs-Map entfernen
            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 definiert formal keine Methode,
            // um zu signalisieren, dass die Transaktion die Operation
            // nicht durchführen konnte
            throw new RuntimeException("Cache flush failed", e);
         }
      }
   }
}

eXtreme-Scale-APIs mit dem TransactionCallback-Plug-in verwenden

Das TransactionCallback-Plug-in inaktiviert die automatische Festschreibung in eXtreme Scale. Im Folgenden sehen Sie das normale Verwendungsmuster für eXtreme Scale:
Session ogSession = ...;
ObjectMap myMap = ogSession.getMap("MyMap");
ogSession.begin();
MyObject v = myMap.get("key");
v.setAttribute("newValue");
myMap.update("key", v);
ogSession.commit();
Wenn dieses TransactionCallback-Plug-in verwendet wird, geht eXtreme Scale davon aus, dass die Anwendung eXtreme Scale verwendet, wenn eine containerverwaltete Transaktion vorhanden ist. Das vorherige Code-Snippet ändert den folgenden Code in dieser Umgebung:
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();
}

Die Methode "myMethod" gleicht einem Webanwendungsszenario. Die Anwendung verwendet die normale Schnittstelle "UserTransaction", um Transaktionen zu starten, festzuschreiben und rückgängig zu machen. eXtreme Scale wird automatisch um die Containertransaktion herum gestartet und festgeschrieben. Wenn die Methode eine EJB-Methode ist, die das Attribut TX_REQUIRES verwendet, entfernen Sie die UserTransaction-Referenz, woraufhin die Aufrufe zum Starten und Festschreiben von Transaktionen und die Methode auf dieselbe Weise funktionieren. In diesem Fall ist der Container für das Starten und Beenden der Transaktion zuständig.