Include Oracle Blockchain Platform in Global Distributed Transactions
Your application might need to make updates across the Oracle Blockchain Platform ledger and other repositories such as databases or other blockchain ledgers in an atomic fashion, where either all updates succeed or none do.
To enable atomic updates across multiple databases, developers use global transactions that are coordinated by distributed transaction coordinators such as Oracle WebLogic Server, Oracle Tuxedo, Oracle Transaction Manager for Microservices, JBoss Enterprise Application Platform, IBM WebSphere, and other systems. All of these systems rely on the X/Open XA protocol to orchestrate a two-phase commit process by using standard APIs that are provided by XA Resource Managers (RMs) for each database or other resource. Oracle Blockchain Platform supports two-phase commits and provides its own XA RM library, which external transaction coordinators can use to invoke XA-compliant APIs. These global transactions can also include a single non-XA resource (for example, a non-Oracle blockchain ledger or non-XA compliant database) by using a last resource commit optimization.
The XA specification is part of the X/Open Distributed Transaction Processing architecture, which defines a standard architecture that enables multiple application programs to share resources provided by multiple resource managers. The Java XA interface itself is defined as part of the Java platform. For more information on the Java XA interface, see Interface XAResource in the Java documentation.
Oracle Blockchain Platform provides a library that conforms to the XA specification and implements the standard Java interface for an XA resource manager. The library enables a client-side transaction manager to coordinate global transactions. A global transaction is a single unit of work that might include operations such as database updates and blockchain transactions, all of which must be committed atomically. In other words, all of the operations must succeed to be committed. If any operation that is part of the global transaction fails, then all operations are rolled back. The XA interface relies on the two-phase commit protocol, similar to the protocol supported by the atomic transactions REST endpoints. For more information about atomic transactions in Oracle Blockchain Platform, see Make Atomic Updates Across Chaincodes and Channels.
The XA implementation for Oracle Blockchain Platform is supplied as a Java library, downloadable from the Developer Tools tab on the Application Development pane of the Oracle Blockchain Platform console.
OBPXAResource
, OBPXADataSource
, and
OBPXAConnection
.
Object | Purpose |
---|---|
OBPXAResource |
This class implements the required APIs for a transaction manager to coordinate with Oracle Blockchain Platform as a resource manager for XA transactions. |
OBPXADataSource |
Use this object to get an instance of the
OBPXAConnection and to specify the
authentication and authorization credentials.
|
OBPXAConnection |
Use this object to get an instance of the
OBPXAResource object and to define the
blockchain transactions to run as part of an XA transaction.
|
To use the XA library with Oracle Blockchain
Platform, the application must provide credentials for authentication and authorization of the requested operations. The library supports both basic authentication (user/password) and OAuth 2.0 access tokens, which you can configure when you create the OBPXADataSource
instance. The two authentication methods are consistent with the authentication methods that you use with the Oracle Blockchain
Platform REST proxy. You can use basic authentication for testing and internal development purposes. Do not use basic authentication in production environments. For more information, see Authentication in the REST API documentation.
OBPXADataSource
instance, you can use
the obpxaDataSource.getXAConnection()
method to get the
xaConnection
instance. To update authentication when using OAuth
2.0 access tokens, you can use the getXAConnection
method, as shown in
the following
code:OBPXAConnection xaConnection = obpxaDataSource.getXAConnection(accessToken); // get an XA connection using an OAuth 2.0 access token
You
can also use the getXAConnection
method to update basic
authentication.OBPXAConnection xaConnection = obpxaDataSource.getXAConnection(user, password); // get an XA connection using username and password for basic authentication
public void createXAInvokeTransaction​(Xid xid, OBPXAInvokeTxRequest invokeTxRequest)
In
this method, xid
is a global transaction identifier and
invokeTxRequest
is the blockchain transaction to be run as part of
the global XA transaction. To create an XA invoke transaction request, you use the
following constructor
method:OBPXAInvokeTxRequest invokeTxRequest = new OBPXAInvokeTxRequest(channel, chaincode, args);
In
this constructor method, channel
is the channel where the blockchain
transaction will run, chaincode
is the chaincode to use, and
args
includes the chaincode function and any arguments to use for
the transaction.
The following snippet of code demonstrates creating an OBPXADataSource
object, getting the OBPXAConnection
instance, and then creating the
transaction request and calling the createXAInvokeTransaction
method.
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);
Scenario: Explore XA Transactions Using Samples
The following scenario is similar to the one described for atomic transactions: Scenario: Explore Atomic Transactions Using Samples, which uses the Balance Transfer and Marbles samples that are included with Oracle Blockchain Platform.
In this scenario, you install the Balance Transfer and Marbles samples on two different instances of Oracle Blockchain Platform. Each instance then corresponds to an XA data source:
- XA resource OBP-1, with the Marbles chaincode installed on the goods channel
- XA resource OBP-2, with the Balance Transfer chaincode installed on the wallet channel
In this scenario, you can use an XA transaction that spans multiple data sources to ensure that the exchange of funds and the marble transfer occur in an atomic manner, where either all operations succeed or none succeed. The following code illustrates this scenario:
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