0
# Programmatic Transaction Management
1
2
Core programmatic API providing simplified transaction control with lambda-style execution, comprehensive semantic options, and automatic leak prevention.
3
4
## Capabilities
5
6
### QuarkusTransaction Core Methods
7
8
The main interface for programmatic transaction management with simplified exception handling.
9
10
```java { .api }
11
/**
12
* Simplified transaction interface with no checked exceptions and automatic leak prevention
13
*/
14
interface QuarkusTransaction {
15
16
/**
17
* Starts a transaction with system default timeout
18
* Transaction is tied to request scope and auto-rolled back if not committed
19
*/
20
static void begin();
21
22
/**
23
* Starts a transaction with custom options
24
* @param options Configuration options for the new transaction
25
*/
26
static void begin(BeginOptions options);
27
28
/** Commits the current transaction */
29
static void commit();
30
31
/** Rolls back the current transaction */
32
static void rollback();
33
34
/** Marks transaction as rollback only - cannot be committed */
35
static void setRollbackOnly();
36
37
/**
38
* Returns transaction status using Jakarta Transaction Status constants
39
* @return Status constant (STATUS_ACTIVE, STATUS_COMMITTED, etc.)
40
*/
41
static int getStatus();
42
43
/**
44
* Checks if transaction is marked for rollback only
45
* @return true if transaction cannot be committed
46
*/
47
static boolean isRollbackOnly();
48
49
/**
50
* @deprecated Use getStatus() instead - the name is misleading
51
* @since 3.22 - scheduled for removal
52
*/
53
@Deprecated
54
static boolean isActive();
55
}
56
```
57
58
**Usage Examples:**
59
60
```java
61
import io.quarkus.narayana.jta.QuarkusTransaction;
62
import jakarta.transaction.Status;
63
64
@ApplicationScoped
65
public class AccountService {
66
67
public void transferFunds(Account from, Account to, BigDecimal amount) {
68
QuarkusTransaction.begin();
69
try {
70
validateSufficientFunds(from, amount);
71
from.withdraw(amount);
72
to.deposit(amount);
73
74
// Check transaction status
75
if (QuarkusTransaction.getStatus() == Status.STATUS_ACTIVE) {
76
QuarkusTransaction.commit();
77
}
78
} catch (InsufficientFundsException e) {
79
QuarkusTransaction.rollback();
80
throw e;
81
} catch (Exception e) {
82
QuarkusTransaction.setRollbackOnly(); // Mark for rollback
83
throw new TransactionException("Transfer failed", e);
84
}
85
}
86
}
87
```
88
89
### BeginOptions Configuration
90
91
Options for customizing transaction begin behavior.
92
93
```java { .api }
94
/**
95
* Configuration options for beginning transactions
96
*/
97
class BeginOptions {
98
99
/**
100
* Automatically commit transaction when request scope ends
101
* By default, transactions are rolled back when request scope is destroyed
102
* @return This BeginOptions instance for chaining
103
*/
104
public BeginOptions commitOnRequestScopeEnd();
105
106
/**
107
* Sets transaction timeout for this specific transaction
108
* @param seconds Timeout in seconds, 0 for system default
109
* @return This BeginOptions instance for chaining
110
* @throws IllegalArgumentException if seconds is negative
111
*/
112
public BeginOptions timeout(int seconds);
113
}
114
```
115
116
**Usage Examples:**
117
118
```java
119
// Transaction with custom timeout
120
QuarkusTransaction.begin(
121
QuarkusTransaction.beginOptions().timeout(30)
122
);
123
124
// Transaction that auto-commits on request scope end
125
QuarkusTransaction.begin(
126
QuarkusTransaction.beginOptions()
127
.commitOnRequestScopeEnd()
128
.timeout(60)
129
);
130
```
131
132
### Transaction Runner Factory Methods
133
134
Factory methods for creating transaction runners with different semantic behaviors.
135
136
```java { .api }
137
/**
138
* Creates transaction runner with REQUIRE_NEW semantics
139
* Always creates new transaction, suspending existing if present
140
*/
141
static TransactionRunnerOptions requiringNew();
142
143
/**
144
* Creates transaction runner with JOIN_EXISTING semantics
145
* Joins existing transaction or creates new one if none exists
146
*/
147
static TransactionRunnerOptions joiningExisting();
148
149
/**
150
* Creates transaction runner with DISALLOW_EXISTING semantics
151
* Throws exception if transaction already exists, otherwise creates new
152
*/
153
static TransactionRunnerOptions disallowingExisting();
154
155
/**
156
* Creates transaction runner with SUSPEND_EXISTING semantics
157
* Suspends existing transaction and runs outside transaction scope
158
*/
159
static TransactionRunnerOptions suspendingExisting();
160
161
/**
162
* Creates transaction runner with specified semantics
163
* @param semantics The transaction propagation behavior to use
164
*/
165
static TransactionRunnerOptions runner(TransactionSemantics semantics);
166
```
167
168
**Usage Examples:**
169
170
```java
171
// Always create new transaction
172
QuarkusTransaction.requiringNew().run(() -> {
173
// This runs in a new transaction regardless of existing transaction
174
auditRepository.logOperation("sensitive_operation");
175
});
176
177
// Join existing or create new
178
int result = QuarkusTransaction.joiningExisting()
179
.timeout(15)
180
.call(() -> {
181
return performDatabaseOperation();
182
});
183
184
// Run outside transaction scope
185
QuarkusTransaction.suspendingExisting().run(() -> {
186
// This runs without any transaction
187
sendEmailNotification();
188
});
189
```
190
191
### Exception Handling
192
193
Exception types and handling for programmatic transaction management.
194
195
```java { .api }
196
/**
197
* Runtime exception wrapping checked exceptions from transaction operations
198
*/
199
class QuarkusTransactionException extends RuntimeException {
200
public QuarkusTransactionException(Throwable cause);
201
public QuarkusTransactionException(String message);
202
public QuarkusTransactionException(String message, Throwable cause);
203
public QuarkusTransactionException(String message, Throwable cause,
204
boolean enableSuppression, boolean writableStackTrace);
205
}
206
```
207
208
**Error Scenarios:**
209
210
```java
211
try {
212
QuarkusTransaction.begin();
213
// ... transaction work
214
QuarkusTransaction.commit();
215
} catch (QuarkusTransactionException e) {
216
// Handles wrapped SystemException, NotSupportedException, etc.
217
logger.error("Transaction failed", e.getCause());
218
// Transaction automatically rolled back
219
}
220
```
221
222
### Deprecated API
223
224
⚠️ **Legacy programmatic methods** - Use TransactionRunnerOptions instead.
225
226
```java { .api }
227
/**
228
* @deprecated Use requiringNew().run(task) instead
229
* Scheduled for removal in future version
230
*/
231
@Deprecated
232
static void run(Runnable task);
233
234
/**
235
* @deprecated Use runner(semantics).run(task) instead
236
* Scheduled for removal in future version
237
*/
238
@Deprecated
239
static void run(RunOptions options, Runnable task);
240
241
/**
242
* @deprecated Use requiringNew().call(task) instead
243
* Scheduled for removal in future version
244
*/
245
@Deprecated
246
static <T> T call(Callable<T> task);
247
248
/**
249
* @deprecated Use runner(semantics).call(task) instead
250
* Scheduled for removal in future version
251
*/
252
@Deprecated
253
static <T> T call(RunOptions options, Callable<T> task);
254
255
/**
256
* @deprecated Use runner() factory methods instead
257
* Scheduled for removal in future version
258
*/
259
@Deprecated
260
static RunOptions runOptions();
261
```
262
263
**Migration Guide for Deprecated Methods:**
264
265
```java
266
// ❌ Old deprecated approach
267
QuarkusTransaction.run(() -> {
268
// transaction work
269
});
270
271
// ✅ New recommended approach
272
QuarkusTransaction.requiringNew().run(() -> {
273
// transaction work
274
});
275
276
// ❌ Old deprecated approach with options
277
QuarkusTransaction.run(QuarkusTransaction.runOptions().semantic(REQUIRE_NEW), () -> {
278
// transaction work
279
});
280
281
// ✅ New recommended approach
282
QuarkusTransaction.runner(TransactionSemantics.REQUIRE_NEW).run(() -> {
283
// transaction work
284
});
285
```
286
287
## Best Practices
288
289
### Request Scope Integration
290
291
Transactions are automatically tied to the CDI request scope:
292
293
```java
294
@RequestScoped
295
public class OrderProcessor {
296
297
public void processOrder(Order order) {
298
QuarkusTransaction.begin();
299
// If this method completes without commit/rollback,
300
// transaction is automatically rolled back when request scope ends
301
302
validateOrder(order);
303
persistOrder(order);
304
// Must explicitly commit
305
QuarkusTransaction.commit();
306
}
307
}
308
```
309
310
### Exception Handling Patterns
311
312
```java
313
public void complexOperation() {
314
QuarkusTransaction.begin();
315
try {
316
step1();
317
step2();
318
step3();
319
QuarkusTransaction.commit();
320
} catch (BusinessException e) {
321
QuarkusTransaction.rollback();
322
throw e; // Re-throw business exceptions
323
} catch (Exception e) {
324
QuarkusTransaction.rollback();
325
throw new ServiceException("Operation failed", e);
326
}
327
}
328
```
329
330
### Performance Considerations
331
332
- Use lambda-style runners for better performance and automatic cleanup
333
- Prefer declarative @Transactional when possible
334
- Set appropriate timeouts for long-running operations
335
- Use SUSPEND_EXISTING for non-transactional operations within transactional methods