Distributed transactions with Atomikos and Bitronix - BEHIND JAVA

Distributed transactions with Atomikos and Bitronix

Share This

What is an XA Transactions

An XA transaction, in the most general terms, is a "global transaction" that may span multiple resources. A non-XA transaction always involves just one resource.

An XA transaction involves a coordinating transaction manager, with one or more databases (or other resources, like JMS) all involved in a single global transaction. Non-XA transactions have no transaction coordinator, and a single resource is doing all its transaction work itself (this is sometimes called local transactions).

jta="true", Transaction commit automatically.

Distributed transactions with multiple databases, Spring Boot, Spring Data JPA and Atomikos Example

We want to be able to save two entities at the same time into two different databases; the operation must be transactional. So, in this example, we have a Customer entity, which is persisted in the first database, and an Order entity which is persisted in the second database. The two entities are very simple, as they serve only as a demonstration.

The resulting implementation is the following. It's worth noting that they belong to two different packages, for two main reasons:

it's a logical separation that gives order to the project each repository will scan packages containing only entities that it will be going to manage

@Data is like having implicit @Getter, @Setter, @ToString, @EqualsAndHashCode and @RequiredArgsConstructor annotations on the class (except that no constructor will be generated if any explicitly written constructor exists).

Write repositories interfaces

Also in this case it's standard, the only thing to notice is that I put the two interfaces in two different packages. The reason is explained in the next step.

Write configuration classes

This is where it becomes interesting. The @DependsOn("transactionManager") annotation is not mandatory, but I needed this to get rid of several warnings at tests (or application) startup, like WARNING: transaction manager not running? in the logs. The next annotation @EnableJpaRepositories is more important:

it specifies which are the packages to scan for annotated components (repository interfaces), and in my case I wanted only repositories related to the customer (and conversely to the order).

it specifies which is the entity manager to be used to manage entities, in my case the customerEntityManager for customer related operations and orderEntityManager for order related operations

it specifies the transaction manager to be used, in my case the transactionManager defined in the MainConfig class. This needs to be the same for every @EnableJpaRepositories to get distributed transactions working

Another important thing here is the definition of the LocalContainerEntityManagerFactoryBean.

  • the @Bean annotation has a given name, that is the one specified in the @EnableJpaRepositories annotation.
  • you need to set some properties to the JpaPropertyMap, in particular you need to say that the transaction type is JTA and that the jta platform is AtomikosJtaPlatform.class.getName()

Write the AbstractJtaPlatform implementation

As said, this is the most important step, as we need to write the implementation of that class by ourselves since Hibernate does not provide it. Here is the resulting code:

Write the main configuration class

Also in this case it's a pretty standard class, with @EnableTransactionManagement annotation and Atomikos bean definitions. The only very important thing to notice is that we need to set AtomikosJtaPlatform.transactionManager and AtomikosJtaPlatform.transaction attributes.

finally the application.properties looks like follows

spring.main.show_banner=false

order.datasource.url=jdbc:h2:order

customer.datasource.url=jdbc:h2:customer

Spring Boot + Bitronix

Distributed transactions in Spring Boot can be implemented using another provider – Bitronix. To change XA provider from Atomikos into Bitronix in previous article example it’s enough to change jta starter and make changes in TransactionManager bean and Data Source implementations. Instead of Atomikos starter we should use

 
     org.springframework.boot
     spring-boot-starter-jta-bitronix
 
 

Configuration class now looks like

No comments:

Post a Comment

Pages