Plug-ins für die Verwaltung von Ereignissen im Lebenszyklus von Transaktionen

Verwenden Sie das TransactionCallback-Plug-in, um Versionssteuerungs- und Vergleichsoperationen für Cacheobjekte anzupassen, wenn Sie die optimistische Sperrstrategie verwenden.

Sie können ein Plug-in-fähiges optimistisches Callback-Objekt bereitstellen, das die Schnittstelle "com.ibm.websphere.objectgrid.plugins.OptimisticCallback" implementiert. Für Entitäts-Maps wird automatisch ein OptimisticCallback-Plug-in mit hoher Leistung konfiguriert.

Zweck

Verwenden Sie die Schnittstelle "OptimisticCallback" für die Unterstützung optimistischer Vergleichsoperationen für die Werte einer Map. Eine OptimisticCallback-Implementierung ist erforderlich, wenn Sie die optimistische Sperrstrategie verwenden. WebSphere eXtreme Scale stellt eine Standardimplementierung von OptimisticCallback bereit. Gewöhnlich muss die Anwendung eine eigene Implementierung der Schnittstelle "OptimisticCallback" integrieren. Weitere Einzelheiten finden Sie in Sperrstrategien.

Standardimplementierung

Das eXtreme-Scale-Framework stellt eine Standardimplementierung der Schnittstelle "OptimisticCallback" bereit, die verwendet wird, wenn die Anwendung kein anwendungsdefiniertes OptimisticCallback-Objekt bereitstellt, wie im folgenden Abschnitt veranschaulicht wird. Die Standardimplementierung gibt immer den Sonderwert NULL_OPTIMISTIC_VERSION als Versionsobjekt für den Wert zurück und aktualisiert das Versionsobjekt nie. Diese Aktion macht einen optimistischen Vergleich zu einer Funktion mit "Nulloperation". In den meisten Fällen ist die Funktion mit "Nulloperation" nicht angebracht, wenn die optimistische Sperrstrategie verwendet wird. Ihre Anwendungen müssen die Schnittstelle "OptimisticCallback" implementieren und eigene OptimisticCallback-Implementierungen integrieren, damit die Standardimplementierung nicht verwendet wird. Es gibt jedoch mindestens ein Szenario, in dem die bereitgestellte OptimisticCallback-Standardimplementierung hilfreich ist. Stellen Sie sich die folgende Situation vor:
  • Es wird ein Loader (Ladeprogramm) für die BackingMap integriert.
  • Der Loader weiß ohne Hilfe eines OptimisticCallback-Plug-ins, wie der optimistische Vergleich durchgeführt wird.
Wie kann der Loader nun ohne Hilfe eines OptimisticCallback-Objekts wissen, wie mit der optimistischen Versionssteuerung zu verfahren ist? Der Loader kennt das Wertobjekt für die Klasse und weiß, welches Feld des Wertobjekts als Wert für die optimistische Versionssteuerung verwendet wird. Angenommen, die folgende Schnittstelle wird für das Wertobjekt der Map "Employee" verwendet:
public interface Employee
{
    // Für die optimistische Versionssteuerung verwendete Folgenummer.
    public long getSequenceNumber();
    public void setSequenceNumber(long newSequenceNumber);
    // Weitere get/set-Methoden für andere Felder des Employee-Objekts.
}

In diesem Fall weiß der Loader, dass er die Methode "getSequenceNumber" verwenden kann, um die aktuellen Versionsinformationen für ein Employee-Wertobjekt abzurufen. Der Loader erhöht den zurückgegebenen Wert um eins, um eine neue Versionsnummer zu generieren, bevor er den persistenten Speicher mit dem neuen Employee-Wert aktualisiert. Für einen JDBC-Loader (Java Database Connectivity) wird die aktuelle Folgenummer in der WHERE-Klausel einer überqualifizierten SQL-Anweisung "update" verwendet. Der Loader verwendet die neu generierte Folgenummer, um die Folgenummernspalte auf den neuen Folgenummernwert zu setzen.

Eine weitere Möglichkeit ist die, dass der Loader eine vom Back-End bereitgestellte Funktion verwendet, die eine verdeckte Spalte, die für die optimistische Versionssteuerung verwendet werden kann, automatisch aktualisiert. In manchen Fällen kann unter Umständen eine gespeicherte Prozedur oder ein Trigger verwendet werden, um eine Spalte zu verwalten, die Informationen zur Versionssteuerung enthält. Wenn der Loader eine dieser Techniken für die Verwaltung der Informationen zur optimistischen Versionssteuerung verwendet, muss die Anwendung keine eigene OptimisticCallback-Implementierung bereitstellen. Sie können die OptimisticCallback-Standardimplementierung verwenden, weil der Loader die optimistische Versionssteuerung ohne Hilfe eines OptimisticCallback-Objekts übernehmen kann.

Standardimplementierung für Entitäten

Entitäten werden im ObjectGrid mit Hilfe von Tupelobjekten gespeichert. Die OptimisticCallback-Standardimplementierung verhält sich ähnlich wie bei Maps, die keine Entitäts-Maps sind. Das Versionsfeld in der Entität wird jedoch mit der Annotation "@Version" bzw. dem Versionsattribut in der XML-Deskriptordatei der Entität angegeben.

Die gültigen Datentypen für das Versionsattribut sind int, Integer, short, Short, long, Long und java.sql.Timestamp. Für eine Entität darf nur ein einziges Versionsattribut definiert werden. Das Versionsattribut darf nur während der Erstellung definiert werden. Sobald die Entität als persistent definiert wird, darf der Wert des Versionsattributs nicht mehr geändert werden.

Wenn kein Versionsattribut konfiguriert ist und die optimistische Sperrstrategie verwendet wird, wird das vollständige Tupel implizit über den Status des Tupels versionsgesteuert.

Im folgenden Beispiel hat die Entität "Employee" ein Versionsattribut mit dem Namen "SequenceNumber" und dem Typ "long":
@Entity
public class Employee
{
private long sequence;
    // Für die optimistische Versionssteuerung verwendete Folgenummer.
    @Version
    public long getSequenceNumber() {
        return sequence;
    }
    public void setSequenceNumber(long newSequenceNumber) {
        this.sequence = newSequenceNumber;
    }
    // Weitere get/set-Methoden für andere Felder des Employee-Objekts.
}

OptimisticCallback-Implementierung schreiben

Ein OptimisticCallback-Plug-in muss die Schnittstelle "OptimisticCallback" implementieren und die folgenden Konventionen für ObjectGrid-Plug-ins einhalten.

Die folgende Liste enthält Beschreibungen und Hinweise für alle Methoden in der Schnittstelle "OptimisticCallback":

NULL_OPTIMISTIC_VERSION

Dieser Sonderwert wird von der Methode "getVersionedObjectForValue" zurückgegeben, wenn die OptimisticCallback-Standardimplementierung an Stelle einer anwendungsdefinierten OptimisticCallback-Implementierung verwendet wird.

Methode "getVersionedObjectForValue"

Die Methode "getVersionedObjectForValue" kann eine Kopie des Werts oder ein Attribut des Werts zurückgeben, das für Versionssteuerungszwecke verwendet werden kann. Diese Methode wird aufgerufen, wenn ein Objekt einer Transaktion zugeordnet wird. Wenn in einer BackingMap kein Loader definiert ist, verwendet die BackingMap diesen Wert während der Festschreibung, um einen optimistischen Versionsvergleich durchzuführen. Der optimistische Versionsvergleich wird von der BackingMap verwendet, um sicherzustellen, dass die Version des Map-Eintrags seit dem ersten Zugriff der Transaktion, die den Map-Eintrag geändert hat, nicht geändert wurde. Wenn eine andere Transaktion die Version für diesen Map-Eintrag bereits geändert hat, schlägt der Versionsvergleich fehl, und die BackingMap zeigt eine Ausnahme des Typs "OptimisticCollisionException" an, um eine Rollback-Operation für die Transaktion zu erzwingen. Wenn ein Loader integriert ist, verwendet die BackingMap die Informationen für die optimistische Versionssteuerung nicht. Stattdessen ist der Loader für die Durchführung der optimistischen Versionssteuerung und die Aktualisierung der Versionssteuerungsinformationen zuständig, sofern dies erforderlich ist. Der Loader ruft gewöhnlich das erste Versionssteuerungsobjekt von dem LogElement-Objekt ab, das an die Methode "batchUpdate" im Loader übergeben wurde, die aufgerufen wird, wenn eine Flush-Operation durchgeführt oder eine Transaktion festgeschrieben wird.

Der folgende Code zeigt die vom EmployeeOptimisticCallbackImpl-Objekt verwendete Implementierung:
public Object getVersionedObjectForValue(Object value)
{
    if (value == null)
    {
        	        return null;
    }
    else
    {
        Employee emp = (Employee) value;
        return new Long( emp.getSequenceNumber() );
    }
}

Wie im vorherigen Beispiel gezeigt, wird das Attribut "sequenceNumber" in einem vom Loader erwarteten Objekt des Typs "java.lang.Long" zurückgegeben. Dies impliziert, dass die Person, die den Loader geschrieben hat, auch die EmployeeOptimisticCallbackImpl-Implementierung geschrieben hat bzw. eng mit der Person zusammengearbeitet hat, die EmployeeOptimisticCallbackImpl implementiert hat, z. B. mit dieser Person den von der Methode "getVersionedObjectForValue" zurückgegebenen Wert vereinbart hat. Wie zuvor beschrieben, gibt die OptimisticCallback-Standardimplementierung den Sonderwert NULL_OPTIMISTIC_VERSION als Versionsobjekt zurück.

Methode "updateVersionedObjectForValue"

Die Methode updateVersionedObjectForValue" wird aufgerufen, wenn eine Transaktion einen Wert aktualisiert hat und ein neues versionsgesteuertes Objekt erforderlich ist. Wenn die Methode "getVersionedObjectForValue" ein Attribut des Werts zurückgibt, aktualisiert diese Methode gewöhnlich den Attributwert mit einem neuen Versionsobjekt. Wenn die Methode "getVersionedObjectForValue" eine Kopie des Werts zurückgibt, führt diese Methode gewöhnlich keine Aktualisierung durch. Die OptimisticCallback-Standardimplementierung führt keine Aktualisierung durch, da die Standardimplementierung der Methode "getVersionedObjectForValue" immer den Sonderwert NULL_OPTIMISTIC_VERSION als Versionsobjekt zurückgibt. Der folgende Beispielcode zeigt die vom EmployeeOptimisticCallbackImpl-Objekt im Abschnitt "OptimisticCallback" verwendete Implementierung:
public void updateVersionedObjectForValue(Object value)
{
    if ( value != null )
    {
        Employee emp = (Employee) value;
        long next = emp.getSequenceNumber() + 1;
        emp.updateSequenceNumber( next );
    }
}

Wie im vorherigen Beispiel gezeigt, wird das Attribut "sequenceNumber" um eins erhöht, so dass beim nächsten Aufruf der Methode "getVersionedObjectForValue" der zurückgegebene Wert vom Typ "java.lang.Long" einen langen Wert hat, der dem ursprünglichen Folgenummernwert plus eins entspricht, z. B. dem nächsten Versionswert für diese Employee-Instanz. Auch hier impliziert das Beispiel, dass die Person, die den Loader geschrieben hat, auch die EmployeeOptimisticCallbackImpl-Implementierung geschrieben hat bzw. eng mit der Person zusammengearbeitet hat, die EmployeeOptimisticCallbackImpl implementiert hat.

Methode "serializeVersionedValue"

Diese Methode schreibt den versionsgesteuerten Wert in den angegebenen Datenstrom. Je nach Implementierung kann der versionsgesteuerte Wert verwendet werden, um optimistische Aktualisierungskollisionen zu identifizieren. In einigen Implementierungen ist der versionsgesteuerte Wert eine Kopie des ursprünglichen Werts. Andere Implementierungen können eine Folgenummer oder ein anderes Objekt haben, um die Version des Werts anzugeben. Da die tatsächliche Implementierung nicht bekannt ist, wird diese Methode bereitgestellt, damit die richtige Serialisierung durchgeführt werden kann. Die Standardimplementierung ruft die Methode "writeObject" auf.

Methode "inflateVersionedValue"

Diese Methode akzeptiert die serialisierte Version des versionsgesteuerten Werts und gibt das tatsächliche versionsgesteuerte Wertobjekt zurück. Je nach Implementierung kann der versionsgesteuerte Wert verwendet werden, um optimistische Aktualisierungskollisionen zu identifizieren. In einigen Implementierungen ist der versionsgesteuerte Wert eine Kopie des ursprünglichen Werts. Andere Implementierungen können eine Folgenummer oder ein anderes Objekt haben, um die Version des Werts anzugeben. Da die tatsächliche Implementierung nicht bekannt ist, wird diese Methode bereitgestellt, damit die richtige Entserialisierung durchgeführt werden kann. Die Standardimplementierung ruft die Methode "readObject" auf.

Anwendungsdefinierte OptimisticCallback-Implementierung verwenden

Sie können zum Hinzufügen eine anwendungsdefinierten OptimisticCallback-Implementierung zur BackingMap-Konfiguration zwischen zwei Ansätzen wählen: der programmgesteuerten Konfiguration und der XML-Konfiguration.

OptimisticCallback-Implementierung über das Programm integrieren

Das folgende Beispiel veranschaulicht, wie eine Anwendung über das Programm ein OptimisticCallback-Objekt für die BackingMap "Employee" in der ObjectGrid-Instanz "grid1" integriert:
import com.ibm.websphere.objectgrid.ObjectGridManagerFactory;
import com.ibm.websphere.objectgrid.ObjectGridManager;
import com.ibm.websphere.objectgrid.ObjectGrid;
import com.ibm.websphere.objectgrid.BackingMap;
ObjectGridManager ogManager = ObjectGridManagerFactory.getObjectGridManager();
ObjectGrid og = ogManager.createObjectGrid( "grid1" );
BackingMap bm = dg.defineMap("employees");
EmployeeOptimisticCallbackImpl cb = new EmployeeOptimisticCallbackImpl();
bm.setOptimisticCallback( cb );

OptimisticCallback-Implementierung durch XML-Konfiguration integrieren

Das EmployeeOptimisticCallbackImpl-Objekt im vorherigen Beispiel muss die Schnittstelle "OptimisticCallback" integrieren. Die Anwendung kann auch eine XML-Datei verwenden, um ihr OptimisticCallback-Objekt zu integrieren, wie im folgenden Beispiel gezeigt wird:
<?xml version="1.0" encoding="UTF-8"?>
<objectGridConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://ibm.com/ws/objectgrid/config ../objectGrid.xsd"
 xmlns="http://ibm.com/ws/objectgrid/config">
<objectGrids>
    <objectGrid name="grid1">
        <backingMap name="employees" pluginCollectionRef="employees" lockStrategy="OPTIMISTIC" />
    </objectGrid>
</objectGrids>

<backingMapPluginCollections>
    <backingMapPluginCollection id="employees">
        <bean id="OptimisticCallback" className="com.xyz.EmployeeOptimisticCallbackImpl" />
    </backingMapPluginCollection>
</backingMapPluginCollections>
</objectGridConfig>