7.2.5 Develop Java Apps that Use Saga and Lock-Free Reservation

MicroTx Saga libraries for Spring REST and Micronaut applications support lock-free reservation.

When microservices use only Oracle Database 23ai as resource manager, you can use Sagas provided by Oracle Database to manage the transaction. If one microservice uses Oracle Database 23ai as resource manager and other microservices use other databases, then you can integrate the MicroTx Saga libraries with Spring REST and Micronaut applications to leverage the lock-free reservation feature in Oracle Database 23ai.

The Lock-Free Reservation feature was introduced in Oracle Database 23ai. See Using Lock-Free Reservation in Database Development Guide.

  1. Set the property values for the MicroTx client library. To enable lock-free reservation, you must set to true the spring.microtx.lra.lock-free-reservation-active property for Spring-REST based apps or the microtx.lra.lock-free-reservation-active property for Micronaut apps. For details about the other library properties, see Configure MicroTx Library Properties for Java Apps.
  2. Import the com.oracle.microtx.lra.lockfree package.
    import com.oracle.microtx.lra.lockfree;
  3. Leverage the MicroTx Lock-free API abstraction by injecting an instance of the MicroTxLockFreeReservation class in the application code before your application logic begins or joins a transaction. The MicroTxLockFreeReservation class implements the LockFreeReservation interface.
    • For Spring-REST based apps, add the following lines of code.
      @Autowired 
      private MicroTxLockFreeReservation microTxLockFreeReservation;
    • For Micronaut apps, add the following lines of code.
      @Inject
      private MicroTxLockFreeReservation microTxLockFreeReservation;
  4. Modify the code of the application that initiates a transaction to demarcate the transaction boundaries and to begin a transaction.
    microTxLockFreeReservation.begin(connection);
    ... // Business logic to begin a transaction.

    Where, connection is the name of the database connection that your application uses to read and write application data to Oracle Database.

  5. Modify the code of the application that participates in the transaction to demarcate the transaction boundaries and to join a transaction.
    microTxLockFreeReservation.join(connection);
    ... // Business logic to join an existing transaction.

    Where, connection is the name of the database connection that your application uses to read and write application data to Oracle Database.

  6. Based on your business logic, complete or compensate the transaction.
    • To complete a transaction:
      microTxLockFreeReservation.complete(connection);
    • To compensate a transaction:
      microTxLockFreeReservation.compensate(connection);

    Where, connection is the name of the database connection that your application uses to read and write application data to Oracle Database.

The following sample code demonstrates how you can demarcate the transaction boundaries using join(), complete(), and compensate() for Spring REST-based application that participates in a transaction. The code lines in bold indicate the lines of code that are added to the existing application code to integrate the MicroTx library. The sample code been truncated with ellipses (...) for readability. You can view the entire sample code in the lra/lockfree folder in the microtx-samples GitHub repository.

import com.oracle.microtx.lra.lockfree;
...
// code specific to application's business logic
...
//Create an instance of the MicroTxLockFreeReservation class
//which implements the LockFreeReservation interface
@Autowired 
private MicroTxLockFreeReservation microTxLockFreeReservation;
...
@RequestMapping(value="/APPLICATION-URL", method = RequestMethod.POST)
@LRA(value=LRA.Type.MANDATORY, end = false)
....

// In the transaction participant application code, 
// provide business logic for the join method so that the
// participant app can join an existing transaction, that MicroTx coordinates.
microTxLockFreeReservation.join(connection);

@RequestMapping(value="/complete", method = RequestMethod.PUT)
@Complete
// application specific business logic to complete the transaction
...

//In transaction initiator and transaction participant application code, 
// provide business logic for the complete and compensate methods so that the
// that MicroTx coordinator can call these methods.
microTxLockFreeReservation.complete(connection);
...

@RequestMapping(value="/compensate", method = RequestMethod.PUT)
@Compensate
// application specific business logic to compensate the transaction
...
//
microTxLockFreeReservation.compensate(connection);
...

In a similar way, you can demarcate the transaction boundaries for a transaction initiator application. The only change is that you call the begin() method to initiate the transaction and you won't call the join() method, which is used only by the participant application.