Spring Boot supports distributed JTA transactions across multiple XA resources using either an Atomikos or Bitronix embedded transaction manager. JTA transactions are also supported when deploying to a suitable Java EE Application Server.
When a JTA environment is detected, Spring’s JtaTransactionManager will be used to
manage transactions. Auto-configured JMS, DataSource and JPA beans will be upgraded to
support XA transactions. You can use standard Spring idioms such as @Transactional to
participate in a distributed transaction. If you are within a JTA environment and still
want to use local transactions you can set the spring.jta.enabled property to false to
disable the JTA auto-configuration.
Atomikos is a popular open source transaction manager which can be embedded into your
Spring Boot application. You can use the spring-boot-starter-jta-atomikos Starter POM to
pull in the appropriate Atomikos libraries. Spring Boot will auto-configure Atomikos and
ensure that appropriate depends-on settings are applied to your Spring beans for correct
startup and shutdown ordering.
By default Atomikos transaction logs will be written to a transaction-logs directory in
your application home directory (the directory in which your application jar file
resides). You can customize this directory by setting a spring.jta.log-dir property in
your application.properties file. Properties starting spring.jta. can also be used to
customize the Atomikos UserTransactionServiceImp. See the
AtomikosProperties Javadoc
for complete details.
![]() | Note |
|---|---|
To ensure that multiple transaction managers can safely coordinate the same
resource managers, each Atomikos instance must be configured with a unique ID. By default
this ID is the IP address of the machine on which Atomikos is running. To ensure
uniqueness in production, you should configure the |
Bitronix is another popular open source JTA transaction manager implementation. You can
use the spring-boot-starter-jta-bitronix starter POM to add the appropriate Bitronix
dependencies to your project. As with Atomikos, Spring Boot will automatically configure
Bitronix and post-process your beans to ensure that startup and shutdown ordering is
correct.
By default Bitronix transaction log files (part1.btm and part2.btm) will be written to
a transaction-logs directory in your application home directory. You can customize this
directory by using the spring.jta.log-dir property. Properties starting spring.jta.
are also bound to the bitronix.tm.Configuration bean, allowing for complete
customization. See the
Bitronix documentation
for details.
![]() | Note |
|---|---|
To ensure that multiple transaction managers can safely coordinate the same
resource managers, each Bitronix instance must be configured with a unique ID. By default
this ID is the IP address of the machine on which Bitronix is running. To ensure
uniqueness in production, you should configure the |
If you are packaging your Spring Boot application as a war or ear file and deploying
it to a Java EE application server, you can use your application servers built-in
transaction manager. Spring Boot will attempt to auto-configure a transaction manager by
looking at common JNDI locations (java:comp/UserTransaction,
java:comp/TransactionManager etc). If you are using a transaction service provided by
your application server, you will generally also want to ensure that all resources are
managed by the server and exposed over JNDI. Spring Boot will attempt to auto-configure
JMS by looking for a ConnectionFactory at the JNDI path java:/JmsXA or
java:/XAConnectionFactory and you can use the
spring.datasource.jndi-name property
to configure your DataSource.
When using JTA, the primary JMS ConnectionFactory bean will be XA aware and participate
in distributed transactions. In some situations you might want to process certain JMS
messages using a non-XA ConnectionFactory. For example, your JMS processing logic might
take longer than the XA timeout.
If you want to use a non-XA ConnectionFactory you can inject the
nonXaJmsConnectionFactory bean rather than the @Primary jmsConnectionFactory bean.
For consistency the jmsConnectionFactory bean is also provided using the bean alias
xaJmsConnectionFactory.
For example:
// Inject the primary (XA aware) ConnectionFactory @Autowired private ConnectionFactory defaultConnectionFactory; // Inject the XA aware ConnectionFactory (uses the alias and injects the same as above) @Autowired @Qualifier("xaJmsConnectionFactory") private ConnectionFactory xaConnectionFactory; // Inject the non-XA aware ConnectionFactory @Autowired @Qualifier("nonXaJmsConnectionFactory") private ConnectionFactory nonXaConnectionFactory;
The XAConnectionFactoryWrapper
and XADataSourceWrapper interfaces
can be used to support alternative embedded transaction managers. The interfaces are
responsible for wrapping XAConnectionFactory and XADataSource beans and exposing them
as regular ConnectionFactory and DataSource beans which will transparently enroll in
the distributed transaction. DataSource and JMS auto-configuration will use JTA variants
as long as you have a JtaTransactionManager bean and appropriate XA wrapper beans
registered within your ApplicationContext.
The BitronixXAConnectionFactoryWrapper and BitronixXADataSourceWrapper provide good examples of how to write XA wrappers.