Spring Boot supports distributed JTA transactions across multiple XA resources by 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
is used to
manage transactions. Auto-configured JMS, DataSource, and JPA beans are 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 to
pull in the appropriate Atomikos libraries. Spring Boot auto-configures Atomikos and
ensures that appropriate depends-on
settings are applied to your Spring beans for
correct startup and shutdown ordering.
By default Atomikos transaction logs are 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 with
spring.jta.atomikos.properties
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 popular open source JTA transaction manager implementation. You can use the
spring-boot-starter-jta-bitronix
starter to add the appropriate Bitronix dependencies
to your project. As with Atomikos, Spring Boot automatically configures Bitronix and
post-processes your beans to ensure that startup and shutdown ordering is correct.
By default, Bitronix transaction log files (part1.btm
and part2.btm
) are written to
a transaction-logs
directory in your application home directory. You can customize this
directory by setting the spring.jta.log-dir
property. Properties starting with
spring.jta.bitronix.properties
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 |
Narayana is popular open source JTA transaction manager implementation supported by
JBoss. You can use the spring-boot-starter-jta-narayana
starter to add the appropriate
Narayana dependencies to your project. As with Atomikos and Bitronix, Spring Boot
automatically configures Narayana and post-processes your beans to ensure that startup
and shutdown ordering is correct.
By default, Narayana transaction logs are 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 with
spring.jta.narayana.properties
can also be used to customize the Narayana
configuration. See the
NarayanaProperties
Javadoc
for complete details.
Note | |
---|---|
To ensure that multiple transaction managers can safely coordinate the same
resource managers, each Narayana instance must be configured with a unique ID. By
default, this ID is set to |
If you package your Spring Boot application as a war
or ear
file and deploy it to a
Java EE application server, you can use your application server’s built-in transaction
manager. Spring Boot tries to auto-configure a transaction manager by looking at common
JNDI locations (java:comp/UserTransaction
, java:comp/TransactionManager
, and so on).
If you use a transaction service provided by your application server, you generally also
want to ensure that all resources are managed by the server and exposed over JNDI. Spring
Boot tries 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 is XA aware and participates
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 by using the bean alias
xaJmsConnectionFactory
.
The following example shows how to inject ConnectionFactory
instances:
// 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 transparently enroll in the
distributed transaction. DataSource and JMS auto-configuration use JTA variants, provided
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.