Managing JTA transactions with the Quarkus transaction manager
Abstract
Preface
As an application developer, you can use the Quarkus transaction manager to coordinate and expose JTA transactions to your applications.
Quarkus provides a transaction manager for coordinating JTA transactions across one or more resources. You can use the Quarkus transaction manager to control transaction boundaries in a declarative or in a programmatic way. You can also modify transactions and configure the transaction timeout. This functionality is provided by the quarkus-narayana-jta
extension.
Providing feedback on Red Hat documentation
We appreciate your feedback on our technical content and encourage you to tell us what you think. If you’d like to add comments, provide insights, correct a typo, or even ask a question, you can do so directly in the documentation.
You must have a Red Hat account and be logged in to the customer portal.
To submit documentation feedback from the customer portal, do the following:
- Select the Multi-page HTML format.
- Click the Feedback button at the top-right of the document.
- Highlight the section of text where you want to provide feedback.
- Click the Add Feedback dialog next to your highlighted text.
- Enter your feedback in the text box on the right of the page and then click Submit.
We automatically create a tracking issue each time you submit feedback. Open the link that is displayed after you click Submit and start watching the issue or add more comments.
Thank you for the valuable feedback.
Making open source more inclusive
Red Hat is committed to replacing problematic language in our code, documentation, and web properties. We are beginning with these four terms: master, slave, blacklist, and whitelist. Because of the enormity of this endeavor, these changes will be implemented gradually over several upcoming releases. For more details, see our CTO Chris Wright’s message.
Chapter 1. Prerequisites
Have OpenJDK (JDK) 11 installed and the
JAVA_HOME
environment variable specifies the location of the Java SDK.- Log in to the Red Hat Customer Portal to download Red Hat build of Open JDK from the Software Downloads page.
Have Apache Maven 3.8.1 or higher installed.
- Download Maven from the Apache Maven Project website.
Have a Quarkus Maven project.
- For information on how to create Quarkus applications with Maven, see Developing and compiling your Quarkus applications with Apache Maven.
Chapter 2. The Narayana JTA transaction manager and Quarkus
The Narayana JTA transaction manager lets you coordinate and expose JTA transactions to your Quarkus applications. You can include the quarkus-narayana-jta
extension as a dependency to your project’s pom.xml
file and manage JTA transactions via annotations that are defined in the the javax.transaction
package or via the Context and dependency injection (CDI).
The following table shows the most common Java Transaction APIs (JTA) annotations. .Java Transaction APIs (JTA) annotations:
Annotation | Description |
---|---|
| Provides the ability to control transaction boundaries on any CDI beans at the method level or class level |
| Provides the ability to specify a standard CDI scope to define bean instances whose life cycle is scoped to the currently active transaction |
You can set attributes on the @Transactional
annotation to control how the transaction starts. You can apply the @Transactional
annotation with attributes to individual methods or to the entire bean.
Chapter 3. Installing the Quarkus Narayana JTA extension
You need to add the quarkus-narayana-jta
extension as a dependency to your Quarkus project. If you are using Hibernate ORM, the quarkus-narayana-jta
extension is already present in your project.
Prerequisites
- Have a Quarkus Maven project.
Procedure
Navigate to the root directory of your project.
cd <directory_name>
Use one of the following methods to add the
quarkus-narayana-jta
extension to your Quarkus project:Add the
quarkus-narayana-jta
extension to yourpom.xml
file:<dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-narayana-jta</artifactId> </dependency>
Add the
quarkus-narayana-jta
extension using the command line:./mvnw quarkus:add-extension -Dextensions="narayana-jta"
Chapter 4. Managing JTA transactions declaratively using the annotations
You can let the container demarcate transaction boundaries by automatically beginning and committing JTA transactions based on annotations. The following chapters demonstrate how you can manage JTA transactions and define transaction boundaries using the @Transactional
annotation.
4.1. Defining transaction boundaries declaratively
You can use @Transactional
to control transaction boundaries on any CDI bean at the method level or at the class level to ensure that every method is transactional. This also applies to REST endpoints.
Procedure
Define the scope of the transaction with the
@Transactional
annotation on the entry method:Example src/main/java/org/acme/SantaClauseService.java
import javax.inject.Inject; import javax.enterprise.context.ApplicationScoped; import javax.transaction.Transactional; @ApplicationScoped public class SantaClausService { @Inject ChildDAO childDAO; @Inject SantaClausDAO santaDAO; @Transactional 1 public void getAGiftFromSanta(Child child, String giftDescription) { // some transaction work Gift gift = childDAO.addToGiftList(child, giftDescription); if (gift == null) { throw new OMGGiftNotRecognizedException(); 2 } else { santaDAO.addToSantaTodoList(gift); } } }
4.2. Configuring a transaction for rollback declaratively
Exceptions caused by system-level faults mark the transactions for rollback and abort the transaction immediately. You can override the default behavior using the @Transactional(dontRollbackOn=SomeException.class)
or the rollbackOn
attribute.
Prerequisites
- Have a Quarkus Maven project.
Procedure
Use the
@Transactional(dontRollbackOn=SomeException.class)
to specify an exception that does not roll back the transaction:Example src/main/java/org/acme/SantaClauseService.java
import javax.inject.Inject; import javax.enterprise.context.ApplicationScoped; import javax.transaction.Transactional; @ApplicationScoped public class SantaClausService { @Inject ChildDAO childDAO; @Inject SantaClausDAO santaDAO; @Transactional(dontRollbackOn=NonCriticalRuntimeException.class) public void getAGiftFromSanta(Child child, String giftDescription) throws Exception { Gift gift = childDAO.addToGiftList(child); // might throw a NonCriticalRuntimeException gift.setDescription(giftDescription); santaDAO.addToSantaTodoList(gift); } }
In this example, the transaction context is propagated to all calls nested in the
@Transactional
method (childDAO.addToGiftList()
andsantaDAO.addToSantaTodoList()
). The transaction commits unless a runtime exception crosses the method boundary.
4.3. Configuring a transaction timeout declaratively
Use the @TransactionConfiguration
annotation in addition to the @Transactional
annotation to specify the timeout in seconds. You can place the @TransactionConfiguration
annotation only on the top-level method that delineates the transaction.
Procedure
Use the
timeout
property of the@TransactionConfiguration
to set the timeout in seconds:import javax.transaction.Transactional; @Transactional @TransactionConfiguration(timeout=40) public void getAGiftFromSanta(Child child, String giftDescription) {...}
The configuration defined on a method takes precedence over the configuration defined on a class. When you define @TransactionConfiguration
on a class, it is equivalent to defining it on all the methods of the class that are marked with @Transactional
.
4.4. Methods returning reactive values
If a method annotated with @Transactional
returns a reactive value it does not terminate the transaction until the returned reactive value is terminated. The transaction is marked for rollback when the reactive value terminates with an exception, otherwise the transaction is committed.
Additional resources
Chapter 5. Managing JTA transactions programmatically using the API approach
You can manage transaction boundaries programmatically by injecting UserTransaction
. The following chapters demonstrate how you can manage JTA transactions and define transaction boundaries using the API approach.
5.1. Defining transaction boundaries using the API approach
You can inject a UserTransaction
and manage the transaction boundaries by calling its begin()
, commit()
and rollback()
methods.
Procedure
Inject the
UserTransaction
interface:src/main/java/org/acme/SantaClauseService.java
@ApplicationScoped public class SantaClausService { @Inject ChildDAO childDAO; @Inject SantaClausDAO santaDAO; @Inject UserTransaction transaction; }
Use the transaction demarcation methods to control the transaction:
src/main/java/org/acme/SantaClauseService.java
import javax.transaction.Transactional; import javax.inject.Inject; import javax.transaction.SystemException; import javax.transaction.UserTransaction; @ApplicationScoped public class SantaClausService { @Inject ChildDAO childDAO; @Inject SantaClausDAO santaDAO; @Inject UserTransaction transaction; public void getAGiftFromSanta(Child child, String giftDescription) { // some transaction work try { transaction.begin(); 1 Gift gift = childDAO.addToGiftList(child, giftDescription); santaDAO.addToSantaTodoList(gift); transaction.commit(); } catch(SomeException e) { // do something on Tx failure transaction.rollback(); 2 } } }
NoteYou cannot use
UserTransaction
in a method where a transaction starts by a@Transactional
call.
5.2. Configuring a transaction for rollback using the API approach
Exceptions caused by system-level faults mark the transactions for rollback. You can mark the transaction for rollback programmatically by injecting TransactionManager
.
Procedure
Inject the
TransactionManager
and set the transaction for rollback withsetRollbackOnly
:In this example, the transaction context is propagated to all calls nested in the
@Transactional
method (childDAO.addToGiftList()
andsantaDAO.addToSantaTodoList()
). The transaction manager commits the transaction unless a runtime exception crosses the method boundary.Example src/main/java/org/acme/SantaClausService.java
import javax.transaction.Transactional; import javax.inject.Inject; import javax.transaction.SystemException; import javax.transaction.UserTransaction; @ApplicationScoped public class SantaClausService { @Inject TransactionManager tm; 1 @Inject ChildDAO childDAO; @Inject SantaClausDAO santaDAO; @Transactional public void getAGiftFromSanta(Child child, String giftDescription) { // some transaction work Gift gift = childDAO.addToGiftList(child, giftDescription); if (gift == null) { tm.setRollbackOnly(); 2 } else { santaDAO.addToSantaTodoList(gift); } } }
Chapter 6. Overwriting the default transaction timeout
You can overwrite the transaction timeout by setting the value for the quarkus.transaction-manager.default-transaction-timeout
property in your application.properties
file. The default timeout for all transactions managed by the transaction manager is 60 seconds. If the transaction is not resolved within the timeout, the transaction manager automatically rolls it back.
Procedure
Set the
<duration>
for thequarkus.transaction-manager.default-transaction-timeout
property in yourapplication.properties
file:quarkus.transaction-manager.default-transaction-timeout=<duration>
You can set the
<duration>
time in seconds or use the standardjava.time.Duration format
. For example, to set the timeout to 2 minutes, enterquarkus.transaction-manager.default-transaction-timeout=PT2M
.
Additional resources
Chapter 7. Configuring the transaction node name identifier for XA transactions
You can set a unique node identifier for XA transactions that have multiple resources. When you create a transaction the node name identifier becomes part of the transaction ID. The identifier allows the transaction manager to recognize the XA transaction counterparts created in a database or by a JMS broker. The transaction manager can roll back the transaction counterparts during recovery.
Procedure
Set a value for the
quarkus.transaction-manager.node-name
property in yourapplication.properties
file:quarkus.transaction-manager.node-name=<unique_id>
NoteMake sure to set a unique node name identifier for each deployment of transaction manager. The node identifier must be stable over the transaction manager restarts.
Chapter 8. Overview of Quarkus transaction configuration properties
The following table lists some of the configuration properties that you can use to configure the transaction management.
Property | Description | Default |
---|---|---|
|
Lets you use regular JDBC transactions, XA, or disable all transactional capabilities ( | enabled |
|
The transaction isolation level ( | |
| The timeout for all transactions managed by the transaction manager | 60 seconds |
| The node name identifier |
Revised on 2021-06-15 14:51:51 UTC