0 day streak
java / intermediate
Snippet

Conditional Programmatic Rollback Control via TransactionAspectSupport

Declarative Spring transactions (`@Transactional`) roll back by default only on unchecked runtime exceptions. When business logic requires a transaction rollback without throwing an exception—such as returning a structured domain response indicating fraud—calling `TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()` cleanly flags the ongoing transaction for rollback during control flow evaluation.

snippet.java
java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Service
public class PaymentProcessingService {
private final LedgerRepository ledgerRepository;
private final ExternalPaymentGateway paymentGateway;
@Transactional
public ProcessingResult processTransaction(PaymentRequest request) {
LedgerEntry entry = ledgerRepository.save(new LedgerEntry(request.getAmount()));
GatewayResponse response = paymentGateway.charge(request.getPaymentMethod(), request.getAmount());
if (response.getStatus() == GatewayStatus.SUSPECTED_FRAUD) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return ProcessingResult.flaggedForReview(entry.getId(), response.getReason());
}
entry.markSettled(response.getTransactionId());
return ProcessingResult.success(entry.getId());
}
}
spring
Breakdown
1
@Transactional
Opens a managed database transaction boundary surrounding the entire method execution.
2
if (response.getStatus() == GatewayStatus.SUSPECTED_FRAUD) {
Evaluates the business logic condition that demands aborting data persistence.
3
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
Directs the active Spring transaction manager to roll back on method completion without throwing an exception.
4
return ProcessingResult.flaggedForReview(entry.getId(), response.getReason());
Allows the method to return a standard result object gracefully despite database rollback.