CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-quarkus--quarkus-narayana-jta

JTA transaction support for Quarkus applications with programmatic and declarative transaction management

Pending
Overview
Eval results
Files

programmatic-transactions.mddocs/

Programmatic Transaction Management

Core programmatic API providing simplified transaction control with lambda-style execution, comprehensive semantic options, and automatic leak prevention.

Capabilities

QuarkusTransaction Core Methods

The main interface for programmatic transaction management with simplified exception handling.

/**
 * Simplified transaction interface with no checked exceptions and automatic leak prevention
 */
interface QuarkusTransaction {
    
    /**
     * Starts a transaction with system default timeout
     * Transaction is tied to request scope and auto-rolled back if not committed
     */
    static void begin();
    
    /**
     * Starts a transaction with custom options
     * @param options Configuration options for the new transaction
     */
    static void begin(BeginOptions options);
    
    /** Commits the current transaction */
    static void commit();
    
    /** Rolls back the current transaction */
    static void rollback();
    
    /** Marks transaction as rollback only - cannot be committed */
    static void setRollbackOnly();
    
    /** 
     * Returns transaction status using Jakarta Transaction Status constants
     * @return Status constant (STATUS_ACTIVE, STATUS_COMMITTED, etc.)
     */
    static int getStatus();
    
    /** 
     * Checks if transaction is marked for rollback only
     * @return true if transaction cannot be committed
     */
    static boolean isRollbackOnly();
    
    /** 
     * @deprecated Use getStatus() instead - the name is misleading
     * @since 3.22 - scheduled for removal 
     */
    @Deprecated
    static boolean isActive();
}

Usage Examples:

import io.quarkus.narayana.jta.QuarkusTransaction;
import jakarta.transaction.Status;

@ApplicationScoped
public class AccountService {
    
    public void transferFunds(Account from, Account to, BigDecimal amount) {
        QuarkusTransaction.begin();
        try {
            validateSufficientFunds(from, amount);
            from.withdraw(amount);
            to.deposit(amount);
            
            // Check transaction status
            if (QuarkusTransaction.getStatus() == Status.STATUS_ACTIVE) {
                QuarkusTransaction.commit();
            }
        } catch (InsufficientFundsException e) {
            QuarkusTransaction.rollback();
            throw e;
        } catch (Exception e) {
            QuarkusTransaction.setRollbackOnly(); // Mark for rollback
            throw new TransactionException("Transfer failed", e);
        }
    }
}

BeginOptions Configuration

Options for customizing transaction begin behavior.

/**
 * Configuration options for beginning transactions
 */
class BeginOptions {
    
    /**
     * Automatically commit transaction when request scope ends
     * By default, transactions are rolled back when request scope is destroyed
     * @return This BeginOptions instance for chaining
     */
    public BeginOptions commitOnRequestScopeEnd();
    
    /**
     * Sets transaction timeout for this specific transaction
     * @param seconds Timeout in seconds, 0 for system default
     * @return This BeginOptions instance for chaining
     * @throws IllegalArgumentException if seconds is negative
     */
    public BeginOptions timeout(int seconds);
}

Usage Examples:

// Transaction with custom timeout
QuarkusTransaction.begin(
    QuarkusTransaction.beginOptions().timeout(30)
);

// Transaction that auto-commits on request scope end
QuarkusTransaction.begin(
    QuarkusTransaction.beginOptions()
        .commitOnRequestScopeEnd()
        .timeout(60)
);

Transaction Runner Factory Methods

Factory methods for creating transaction runners with different semantic behaviors.

/**
 * Creates transaction runner with REQUIRE_NEW semantics
 * Always creates new transaction, suspending existing if present
 */
static TransactionRunnerOptions requiringNew();

/**
 * Creates transaction runner with JOIN_EXISTING semantics  
 * Joins existing transaction or creates new one if none exists
 */
static TransactionRunnerOptions joiningExisting();

/**
 * Creates transaction runner with DISALLOW_EXISTING semantics
 * Throws exception if transaction already exists, otherwise creates new
 */
static TransactionRunnerOptions disallowingExisting();

/**
 * Creates transaction runner with SUSPEND_EXISTING semantics
 * Suspends existing transaction and runs outside transaction scope
 */
static TransactionRunnerOptions suspendingExisting();

/**
 * Creates transaction runner with specified semantics
 * @param semantics The transaction propagation behavior to use
 */
static TransactionRunnerOptions runner(TransactionSemantics semantics);

Usage Examples:

// Always create new transaction
QuarkusTransaction.requiringNew().run(() -> {
    // This runs in a new transaction regardless of existing transaction
    auditRepository.logOperation("sensitive_operation");
});

// Join existing or create new
int result = QuarkusTransaction.joiningExisting()
    .timeout(15)
    .call(() -> {
        return performDatabaseOperation();
    });

// Run outside transaction scope
QuarkusTransaction.suspendingExisting().run(() -> {
    // This runs without any transaction
    sendEmailNotification();
});

Exception Handling

Exception types and handling for programmatic transaction management.

/**
 * Runtime exception wrapping checked exceptions from transaction operations
 */
class QuarkusTransactionException extends RuntimeException {
    public QuarkusTransactionException(Throwable cause);
    public QuarkusTransactionException(String message);
    public QuarkusTransactionException(String message, Throwable cause);
    public QuarkusTransactionException(String message, Throwable cause, 
                                     boolean enableSuppression, boolean writableStackTrace);
}

Error Scenarios:

try {
    QuarkusTransaction.begin();
    // ... transaction work
    QuarkusTransaction.commit();
} catch (QuarkusTransactionException e) {
    // Handles wrapped SystemException, NotSupportedException, etc.
    logger.error("Transaction failed", e.getCause());
    // Transaction automatically rolled back
}

Deprecated API

⚠️ Legacy programmatic methods - Use TransactionRunnerOptions instead.

/** 
 * @deprecated Use requiringNew().run(task) instead 
 * Scheduled for removal in future version
 */
@Deprecated
static void run(Runnable task);

/** 
 * @deprecated Use runner(semantics).run(task) instead
 * Scheduled for removal in future version  
 */
@Deprecated
static void run(RunOptions options, Runnable task);

/** 
 * @deprecated Use requiringNew().call(task) instead 
 * Scheduled for removal in future version
 */
@Deprecated
static <T> T call(Callable<T> task);

/** 
 * @deprecated Use runner(semantics).call(task) instead 
 * Scheduled for removal in future version
 */
@Deprecated  
static <T> T call(RunOptions options, Callable<T> task);

/** 
 * @deprecated Use runner() factory methods instead
 * Scheduled for removal in future version 
 */
@Deprecated
static RunOptions runOptions();

Migration Guide for Deprecated Methods:

// ❌ Old deprecated approach
QuarkusTransaction.run(() -> {
    // transaction work
});

// ✅ New recommended approach  
QuarkusTransaction.requiringNew().run(() -> {
    // transaction work
});

// ❌ Old deprecated approach with options
QuarkusTransaction.run(QuarkusTransaction.runOptions().semantic(REQUIRE_NEW), () -> {
    // transaction work  
});

// ✅ New recommended approach
QuarkusTransaction.runner(TransactionSemantics.REQUIRE_NEW).run(() -> {
    // transaction work
});

Best Practices

Request Scope Integration

Transactions are automatically tied to the CDI request scope:

@RequestScoped
public class OrderProcessor {
    
    public void processOrder(Order order) {
        QuarkusTransaction.begin();
        // If this method completes without commit/rollback,
        // transaction is automatically rolled back when request scope ends
        
        validateOrder(order);
        persistOrder(order);
        // Must explicitly commit
        QuarkusTransaction.commit();
    }
}

Exception Handling Patterns

public void complexOperation() {
    QuarkusTransaction.begin();
    try {
        step1();
        step2();
        step3();
        QuarkusTransaction.commit();
    } catch (BusinessException e) {
        QuarkusTransaction.rollback();
        throw e; // Re-throw business exceptions
    } catch (Exception e) {
        QuarkusTransaction.rollback();
        throw new ServiceException("Operation failed", e);
    }
}

Performance Considerations

  • Use lambda-style runners for better performance and automatic cleanup
  • Prefer declarative @Transactional when possible
  • Set appropriate timeouts for long-running operations
  • Use SUSPEND_EXISTING for non-transactional operations within transactional methods

Install with Tessl CLI

npx tessl i tessl/maven-io-quarkus--quarkus-narayana-jta

docs

configuration.md

declarative-transactions.md

index.md

programmatic-transactions.md

transaction-semantics.md

tile.json