A transaction initiator service initiates or starts a transaction. Based on your application's business logic, a transaction initiator service may only start the transaction or start the transaction and participate in the transaction as well.
Before you begin, identify if your application only initiates the transaction or initiates and participates in the transaction. Configure your application accordingly as the requirements vary slightly for the two scenarios.
Let us consider two scenarios to understand if your application only initiates the transaction or participates in the transaction as well.
- Scenario 1: A banking teller application transfers an amount from one department to another. Here, the teller application only initiates the transaction and does not participate in it. Based on the business logic, the teller application calls different services to complete the transaction. A database instance may or may not be attached to the teller application.
- Scenario 2: A banking teller application transfers an amount from one department to another. For every transaction, the teller application charges 1% as commission. Here, the teller application initiates the transaction and participates in it. A database instance must be attached to the teller application to save the transaction information.
To configure your Spring Boot 3.x application as a transaction initiator using Spring REST or JAX-RS:
- Specify property values for the MicroTx library. See Configure Library Properties for Spring Boot Apps.
- Include MicroTx library files as a maven dependency in the Spring Boot 3.x application's
pom.xml
file. The following sample code is for the 24.4 release. Provide the correct version, based on the release version that you want to use. Spring Boot 3.x applications work with Java 17.
-
For JDBC applications, use the microtx-spring-boot-starter
file.
<dependency>
<groupId>com.oracle.microtx</groupId>
<artifactId>microtx-spring-boot-starter</artifactId>
<version>24.4</version>
</dependency>
-
When Hibernate is the JPA provider, use the microtx-spring-boot-starter
and microtx-spring-boot-starter-hibernate
files.
<dependency>
<groupId>com.oracle.microtx</groupId>
<artifactId>microtx-spring-boot-starter</artifactId>
<version>24.4</version>
</dependency>
<dependency>
<groupId>com.oracle.microtx</groupId>
<artifactId>microtx-spring-boot-starter-hibernate</artifactId>
<version>24.4</version>
</dependency>
-
When EclipseLink is the JPA provider, use the microtx-spring-boot-starter
and microtx-spring-boot-starter-eclipselink
files.
<dependency>
<groupId>com.oracle.microtx</groupId>
<artifactId>microtx-spring-boot-starter</artifactId>
<version>24.4</version>
</dependency>
<dependency>
<groupId>com.oracle.microtx</groupId>
<artifactId>microtx-spring-boot-starter-eclipselink</artifactId>
<version>24.4</version>
</dependency>
-
For JDBC applications, use the microtx-spring-boot-jaxrs-starter
file.
<dependency>
<groupId>com.oracle.microtx</groupId>
<artifactId>microtx-spring-boot-jaxrs-starter</artifactId>
<version>24.4</version>
</dependency>
-
When Hibernate is the JPA provider, use the microtx-spring-boot-jaxrs-starter
and microtx-spring-boot-starter-hibernate
files.
<dependency>
<groupId>com.oracle.microtx</groupId>
<artifactId>microtx-spring-boot-jaxrs-starter</artifactId>
<version>24.4</version>
</dependency>
<dependency>
<groupId>com.oracle.microtx</groupId>
<artifactId>microtx-spring-boot-starter-hibernate</artifactId>
<version>24.4</version>
</dependency>
-
When EclipseLink is the JPA provider, use the microtx-spring-boot-jaxrs-starter
and microtx-spring-boot-starter-eclipselink
files.
<dependency>
<groupId>com.oracle.microtx</groupId>
<artifactId>microtx-spring-boot-jaxrs-starter</artifactId>
<version>24.4</version>
</dependency>
<dependency>
<groupId>com.oracle.microtx</groupId>
<artifactId>microtx-spring-boot-starter-eclipselink</artifactId>
<version>24.4</version>
</dependency>
- Only for Spring JAX-RS applications, you must register the following filters so that the MicroTx library can intercept the JAX-RS calls and manage the transaction. You can skip this step for Spring REST applications.
import org.glassfish.jersey.server.ResourceConfig;
...
@Component
public class Configuration extends ResourceConfig {
public Configuration() {
...
register(TrmTransactionRequestFilter.class);
register(TrmTransactionResponseFilter.class);
register(JaxRsXACallbackResource.class);
}
- Complete the following steps if you want to use the
@Transactional
annotation. See About @Transactional.
- Import the
org.springframework.transaction.annotation.Transactional
package.import org.springframework.transaction.annotation.Transactional;
- Annotate the method which initiates the transaction with
@Transactional
. The following code sample demonstrates the usage of @Transactional
.import org.springframework.transaction.annotation.Transactional;
...
@RequestMapping(value = "", method = RequestMethod.POST)
@Transactional(propagation = Propagation.REQUIRED, timeout = 60)
public ResponseEntity<?> transfer(@RequestBody Transfer transferDetails) {
// code that is specific to the application's business logic
// withdraw operation on participant service 1
// deposit operation on participant service 2
}
For details about using @Transactional
for Spring Boot apps, see https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/annotation/Transactional.html.
- Ensure that the method returns a
ResponseEntity
object as shown in the example. This is required by the MicroTx library to handle the transaction and trigger the ResponseBodyFilter
class. In MicroTx, the com.oracle.microtx.springboot.interceptor.ResponseBodyFilter
class is declared with @ControllerAdvice
.
- Skip to step 9 as you don't have to specify the transaction boundaries using
begin()
, commit()
, and rollback()
when you use @Transactional
.
- Import the
com.oracle.microtx.xa.rm.MicroTxUserTransactionService
package.import com.oracle.microtx.xa.rm.MicroTxUserTransactionService;
- Autowire the
MicroTxUserTransactionService
class before your application logic initiates or begins a transaction.@Autowired
MicroTxUserTransactionService microTxUserTransactionService;
- Optional. Specify the amount of time, in milliseconds, for which the transaction remains active. If a transaction is not committed or rolled back within the specified time period, the transaction is rolled back. This overrides the
spring.microtx.xa-transaction-timeout
property value in the application.yaml
file. See Set Transaction Timeout.microTxUserTransaction.setTransactionTimeout(60000);
- Ensure that the method returns a
ResponseEntity
object as shown in the example. @RequestMapping(value = "", method = RequestMethod.POST)
public ResponseEntity<?> transfer(@RequestBody Transfer transferDetails)
{
...
}
This is required by the
MicroTx library to handle the transaction and trigger the
ResponseBodyFilter
class. In
MicroTx, the
com.oracle.microtx.springboot.interceptor.ResponseBodyFilter
class is declared with
@ControllerAdvice
.
- Within the application code that initiates the transaction, demarcate the transaction boundaries, such as to begin, commit, or roll back the transactions. The following code sample demonstrates how to begin a new XA transaction.
-
If your application only initiates the transaction and does not participate in the transaction, add the following line to your application code to begin the XA transaction.
microTxUserTransactionService.begin();
... // Implement the business logic to begin a transaction.
-
If your application initiates the transaction and participates in it, add the following line to your application code to begin the XA transaction.
microTxUserTransactionService.begin(true);
... // Implement the business logic to begin a transaction.
- Based on your business logic, commit or rollback the transaction.
-
To commit a transaction:
microTxUserTransactionService.commit();
-
To rollback a transaction:
microTxUserTransactionService.rollback();
The following code sample demonstrates how you can demarcate the transaction boundaries using begin()
, commit()
, and rollback()
.
@RequestMapping(value = "", method = RequestMethod.POST)
public ResponseEntity<?> transfer(@RequestBody Transfer transferDetails) {
microTxUserTransactionService.begin();
// app specific code
try {
microTxUserTransactionService.commit();
} catch (Exception e) {
microTxUserTransactionService.rollback();
}
}
- Use a REST template or OpenFeign to call the endpoints of the transaction participant services to perform the transaction. The transaction initiator service begins the transaction. To complete the transaction, a initiator service may have to call one or more participant services. While calling the participant services, use the object that you create.
Autowire the Spring Boot RestTemplate
, provided by the MicroTx library as shown in the following sample code.
@Autowired
@Qualifier("MicroTxXaRestTemplate")
RestTemplate restTemplate;
Configure an interceptor, provided by the MicroTx library, in one of the following ways. This is required if an outgoing request is a part of a transaction or if you want to intercept an outgoing request.
- Configure an interceptor in the configuration property of the
@FeignClient
annotation as shown in the following example. @FeignClient(value = "<feign1.name>", url = "<feign1.url>", configuration = MicroTxXaFeignInterceptorConfig.class)
public interface <interface_name> {
// ...
}
Where, you replace <feign1.name>
and <feign1.url>
with values specific to your environment. Note down the name of the interface as you will use it later in your application code.
- Configure interceptors by specifying property values as shown in the following example. Provide these values in the same file that contains values for the MicroTx client library properties.
spring.cloud.openfeign.client.config.<feign1_name>.request-interceptors[0]= com.oracle.microtx.springboot.xa.clientinterceptor.MicroTxXaFeignInterceptorConfig
Where, <feign1_name>
is the data for the value
property of the @FeignClient
annotation.
- Save your changes.
Source code of a sample Spring REST transaction initiator application which uses the
MicroTx library and XA is available in the
teller-spring
folder which is located in the
microtx-samples
GitHub repository. You can use this as a reference while integrating the MicroTx libraries with your application. This provides an example of how you can use the
MicroTx Spring REST libraries with the business logic of your Spring REST initiator application. This sample application is called Teller. It initiates a transaction between two departments. It calls Dept A to withdraw an amount and it calls Dept B to deposit the amount.
If the initiator service also participates in the transaction in addition to initiating the transaction, you must make additional configurations for the application to participate in the transaction and communicate with the resource manager. See
Configure Spring Boot App as Transaction Participant. The
teller-as-participant-spring
folder which is located in the
microtx-samples
GitHub repository provides the source code of a Spring REST transaction initiator application which also participates in the transaction.