Oracle Blockchain Platform in globale verteilte Transaktionen aufnehmen

Ihre Anwendung muss möglicherweise Updates im Oracle Blockchain Platform-Ledger und in anderen Repositorys wie Datenbanken oder anderen Blockchain-Ledgern atomar vornehmen, wobei entweder alle Updates erfolgreich sind oder keine ausgeführt werden.

Um atomare Updates über mehrere Datenbanken hinweg zu ermöglichen, verwenden Entwickler globale Transaktionen, die von verteilten Transaktionskoordinatoren wie Oracle WebLogic Server, Oracle Tuxedo, Oracle Transaction Manager for Microservices, JBoss Enterprise Application Platform, IBM WebSphere und anderen Systemen koordiniert werden. Alle diese Systeme verlassen sich auf das X/Open XA-Protokoll, um einen zweiphasigen Commit-Prozess mit Standard-APIs zu orchestrieren, die von XA Resource Managers (RMs) für jede Datenbank oder andere Ressource bereitgestellt werden. Oracle Blockchain Platform unterstützt zweiphasige Commits und stellt eine eigene XA RM-Bibliothek bereit, mit der externe Transaktionskoordinatoren XA-konforme APIs aufrufen können. Diese globalen Transaktionen können auch eine einzelne Nicht-XA-Ressource (z.B. ein nicht-Oracle-Blockchain-Ledger oder eine nicht-XA-konforme Datenbank) umfassen, indem eine letzte Ressourcen-Commit-Optimierung verwendet wird.

Die XA-Spezifikation ist Teil der X/Open Distributed Transaction Processing-Architektur, die eine Standardarchitektur definiert, mit der mehrere Anwendungsprogramme Ressourcen gemeinsam nutzen können, die von mehreren Ressourcenmanagern bereitgestellt werden. Die Java XA-Schnittstelle selbst ist als Teil der Java-Plattform definiert. Weitere Informationen zur Java XA-Schnittstelle finden Sie unter Schnittstelle XAResource in der Java-Dokumentation.

Oracle Blockchain Platform stellt eine Library bereit, die der XA-Spezifikation entspricht und die standardmäßige Java-Schnittstelle für einen XA-Ressourcenmanager implementiert. Mit der Bibliothek kann ein clientseitiger Transaktionsmanager globale Transaktionen koordinieren. Eine globale Transaktion ist eine einzelne Arbeitseinheit, die Vorgänge wie Datenbankaktualisierungen und Blockchain-Transaktionen umfassen kann, die alle atomar festgeschrieben werden müssen. Mit anderen Worten, alle Operationen müssen erfolgreich durchgeführt werden. Wenn ein Vorgang, der Teil der globalen Transaktion ist, nicht erfolgreich verläuft, werden alle Vorgänge zurückgesetzt. Die XA-Schnittstelle basiert auf dem Two-Phase Commit-Protokoll, ähnlich dem Protokoll, das von den REST-Endpunkten für atomare Transaktionen unterstützt wird. Weitere Informationen zu atomaren Transaktionen in Oracle Blockchain Platform finden Sie unter Atomare Updates über Chaincodes und Kanäle hinweg vornehmen.

Die XA-Implementierung für Oracle Blockchain Platform wird als Java-Library bereitgestellt und kann auf der Registerkarte Entwicklungstools im Bereich Anwendungsentwicklung der Oracle Blockchain Platform-Konsole heruntergeladen werden.

Ausführliche Informationen zur Bibliothek finden Sie in den Javadoc-Informationen in der herunterladbaren Datei. Die drei von der Bibliothek unterstützten Schlüsselobjekte sind OBPXAResource, OBPXADataSource und OBPXAConnection.
Objekt Zweck
OBPXAResource Diese Klasse implementiert die erforderlichen APIs für die Koordination eines Transaktionsmanagers mit Oracle Blockchain Platform als Ressourcenmanager für XA-Transaktionen.
OBPXADataSource Verwenden Sie dieses Objekt, um eine Instanz von OBPXAConnection abzurufen und die Authentifizierungs- und Autorisierungszugangsdaten anzugeben.
OBPXAConnection Verwenden Sie dieses Objekt, um eine Instanz des OBPXAResource-Objekts abzurufen und die Blockchain-Transaktionen zu definieren, die als Teil einer XA-Transaktion ausgeführt werden sollen.

Um die XA-Bibliothek mit Oracle Blockchain Platform verwenden zu können, muss die Anwendung Zugangsdaten für die Authentifizierung und Autorisierung der angeforderten Vorgänge angeben. Die Bibliothek unterstützt sowohl grundlegende Authentifizierungstoken (Benutzer/Kennwort) als auch Zugriffstoken der Version OAuth 2.0, die Sie beim Erstellen der OBPXADataSource-Instanz konfigurieren können. Die beiden Authentifizierungsmethoden sind mit den Authentifizierungsmethoden konsistent, die Sie mit dem Oracle Blockchain Platform-REST-Proxy verwenden. Sie können die Basisauthentifizierung zu Test- und internen Entwicklungszwecken verwenden. Verwenden Sie keine Basisauthentifizierung in Produktionsumgebungen. Weitere Informationen finden Sie unter Authentifizierung in der REST-API-Dokumentation.

Nachdem Sie eine OBPXADataSource-Instanz erstellt haben, können Sie die xaConnection-Instanz mit der Methode obpxaDataSource.getXAConnection() abrufen. Um die Authentifizierung bei Verwendung von OAuth 2.0-Zugriffstoken zu aktualisieren, können Sie die Methode getXAConnection verwenden, wie im folgenden Code dargestellt:
OBPXAConnection xaConnection = obpxaDataSource.getXAConnection(accessToken);      // get an XA connection using an OAuth 2.0 access token
Sie können auch die Methode getXAConnection verwenden, um die Basisauthentifizierung zu aktualisieren.
OBPXAConnection xaConnection = obpxaDataSource.getXAConnection(user, password);   // get an XA connection using username and password for basic authentication
Um eine Blockchain-Transaktion zu definieren, die als Teil einer globalen XA-Transaktion ausgeführt werden soll, verwenden Sie die folgende Methode:
public void createXAInvokeTransaction​(Xid xid, OBPXAInvokeTxRequest invokeTxRequest)
Bei dieser Methode ist xid eine globale Transaktions-ID und invokeTxRequest die Blockchain-Transaktion, die im Rahmen der globalen XA-Transaktion ausgeführt werden soll. Um eine XA-Aufruftransaktionsanforderung zu erstellen, verwenden Sie die folgende Konstruktormethode:
OBPXAInvokeTxRequest invokeTxRequest = new OBPXAInvokeTxRequest(channel, chaincode, args);
In dieser Konstruktormethode ist channel der Kanal, in dem die Blockchain-Transaktion ausgeführt wird, chaincode der zu verwendende Chaincode und args die Chaincodefunktion und alle Argumente, die für die Transaktion verwendet werden sollen.

Das folgende Code-Snippet zeigt das Erstellen eines OBPXADataSource-Objekts, das Abrufen der OBPXAConnection-Instanz, das Erstellen der Transaktionsanforderung und das Aufrufen der createXAInvokeTransaction-Methode.

OBPXADataSource obpxaDataSource = OBPXADataSource.builder()
                        .withHost(host)
                        .withPort(port)
                        .withBasicAuth(username, password)
                        .withRole(role)
                        .build();
.
.
.
OBPXAConnection obpxaConnection = obpxaDataSource.getXAConnection();

OBPXAInvokeTxRequest invokeTxRequest = new OBPXAInvokeTxRequest(channel, chaincode, args);
invokeTxRequest.setEndorsers(endorsersArray); // optional blockchain transaction request attributes
invokeTxRequest.setTransientMap(transientMap); // optional blockchain transaction request attributes
invokeTxRequest.setTimeout(60000); // optional blockchain transaction request attributes

obpxaConnection.createXAInvokeTransaction​(xid, invokeTxRequest);

Szenario: XA-Transaktionen mit Beispielen untersuchen

Das folgende Szenario ähnelt dem für atomare Transaktionen beschriebenen Szenario: Szenario: Atomare Transaktionen mit Beispielen untersuchen, das die in Oracle Blockchain Platform enthaltenen Muster "Saldotransfer" und "Marbles" verwendet.

In diesem Szenario installieren Sie die Balance Transfer- und Marbles-Beispiele auf zwei verschiedenen Instanzen von Oracle Blockchain Platform. Jede Instanz entspricht dann einer XA-Datenquelle:

  • XA-Ressource OBP-1, wobei der Marbles-Kettencode im Warenkanal installiert ist
  • XA-Ressource OBP-2, wobei der Balance Transfer-Kettencode auf dem Wallet-Kanal installiert ist

In diesem Szenario können Sie eine XA-Transaktion verwenden, die sich über mehrere Datenquellen erstreckt, um sicherzustellen, dass der Geldaustausch und der Marmortransfer atomar erfolgen, wobei entweder alle Operationen erfolgreich oder keine erfolgreich sind. Der folgende Code veranschaulicht dieses Szenario:

OBPXADataSource obpxaDS1 = ... // create an XA data source, supplying details about the OBP-1 instance
OBPXADataSource obpxaDS2 = ... // create an XA data source, supplying details about the OBP-2 instance

// start a global transaction in the client application
// invoke marble transfer on OBP-1
OBPXAConnection obpxaConn1 = (OBPXAConnection) obpxaDS1.getXAConnection();
OBPXAInvokeTxRequest invokeMarbleTransferReq = new OBPXAInvokeTxRequest("goods", "obcs-marbles", new String[]{"transferMarble", "marble1", "tom"});
obpxaConn1.createXAInvokeTransaction​(xid1, invokeMarbleTransferReq);
.
.
.
// invoke fund transfer on OBP-2
OBPXAConnection obpxaConn2 = (OBPXAConnection) obpxaDS2.getXAConnection();
OBPXAInvokeTxRequest invokeBalanceTransferReq = new OBPXAInvokeTxRequest("wallet", "obcs-example02", new String[]{"invoke", "a", "b", "50"});
obpxaConn2.createXAInvokeTransaction​(xid2, invokeBalanceTransferReq);
.
.
.
// end the global transaction in the client application