or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

aop-interceptors.mddao-support.mddeclarative-transactions.mdexception-hierarchy.mdindex.mdjca-support.mdprogrammatic-transactions.mdreactive-transactions.mdtransaction-events.mdtransaction-managers.mdtransaction-synchronization.md
tile.json

transaction-managers.mddocs/

Transaction Managers

Transaction managers are the central abstraction in Spring's transaction infrastructure. They abstract over different transaction APIs (JTA, JDBC, Hibernate, JPA) providing a consistent programming model.

Capabilities

PlatformTransactionManager

Central interface for imperative transaction management. All transaction manager implementations must implement this interface.

/**
 * Central interface for imperative transaction management.
 * This is the main abstraction for transaction management in Spring.
 */
public interface PlatformTransactionManager extends TransactionManager {

    /**
     * Get a transaction according to the specified definition, or create a new one
     * if necessary. Returns a TransactionStatus object that can be used to control
     * transaction execution and query transaction status.
     *
     * @param definition TransactionDefinition instance (can be null for defaults)
     * @return transaction status object representing the new or current transaction
     * @throws TransactionException in case of lookup, creation, or system errors
     */
    TransactionStatus getTransaction(TransactionDefinition definition)
            throws TransactionException;

    /**
     * Commit the given transaction. If the transaction has been marked rollback-only
     * programmatically, perform a rollback.
     *
     * @param status object returned by getTransaction
     * @throws TransactionException in case of commit or system errors
     */
    void commit(TransactionStatus status) throws TransactionException;

    /**
     * Rollback the given transaction.
     *
     * @param status object returned by getTransaction
     * @throws TransactionException in case of system errors
     */
    void rollback(TransactionStatus status) throws TransactionException;
}

Usage Example:

import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

@Service
public class ManualTransactionService {

    private final PlatformTransactionManager transactionManager;

    public ManualTransactionService(PlatformTransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }

    public void executeWithManualControl() {
        // Create transaction definition
        TransactionDefinition def = new DefaultTransactionDefinition();

        // Start transaction
        TransactionStatus status = transactionManager.getTransaction(def);

        try {
            // Execute business logic
            performDatabaseOperations();

            // Commit transaction
            transactionManager.commit(status);
        } catch (Exception e) {
            // Rollback on error
            transactionManager.rollback(status);
            throw e;
        }
    }

    private void performDatabaseOperations() {
        // Database operations here
    }
}

JtaTransactionManager

PlatformTransactionManager implementation for JTA (Java Transaction API). Used for distributed transactions and integration with Java EE application servers.

/**
 * PlatformTransactionManager implementation for JTA.
 * Supports distributed transactions across multiple resources.
 */
public class JtaTransactionManager extends AbstractPlatformTransactionManager
        implements TransactionFactory, InitializingBean, Serializable {

    /** Default JNDI location for UserTransaction */
    public static final String DEFAULT_USER_TRANSACTION_NAME = "java:comp/UserTransaction";

    /** Default JNDI location for TransactionSynchronizationRegistry */
    public static final String DEFAULT_TRANSACTION_SYNCHRONIZATION_REGISTRY_NAME =
        "java:comp/TransactionSynchronizationRegistry";

    /**
     * Create a new JtaTransactionManager instance.
     */
    public JtaTransactionManager();

    /**
     * Create a new JtaTransactionManager instance with the given UserTransaction.
     */
    public JtaTransactionManager(UserTransaction userTransaction);

    /**
     * Create a new JtaTransactionManager instance with the given
     * UserTransaction and TransactionManager.
     */
    public JtaTransactionManager(
        UserTransaction userTransaction,
        TransactionManager transactionManager
    );

    /**
     * Set the JTA UserTransaction to use.
     */
    public void setUserTransaction(UserTransaction userTransaction);

    /**
     * Set the JNDI name of the JTA UserTransaction.
     */
    public void setUserTransactionName(String userTransactionName);

    /**
     * Set the JTA TransactionManager to use.
     */
    public void setTransactionManager(TransactionManager transactionManager);

    /**
     * Set the JNDI name of the JTA TransactionManager.
     */
    public void setTransactionManagerName(String transactionManagerName);

    /**
     * Set the JTA TransactionSynchronizationRegistry to use.
     */
    public void setTransactionSynchronizationRegistry(
        TransactionSynchronizationRegistry transactionSynchronizationRegistry
    );

    /**
     * Set the JNDI name of the JTA TransactionSynchronizationRegistry.
     */
    public void setTransactionSynchronizationRegistryName(String name);

    /**
     * Set whether to allow custom isolation levels on JTA transactions.
     * Default is false.
     */
    public void setAllowCustomIsolationLevels(boolean allowCustomIsolationLevels);
}

Usage Examples:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.jta.JtaTransactionManager;

@Configuration
public class JtaConfig {

    // Basic JTA configuration with default JNDI lookups
    @Bean
    public JtaTransactionManager transactionManager() {
        JtaTransactionManager txManager = new JtaTransactionManager();
        // Will look up UserTransaction at default location
        return txManager;
    }

    // With explicit UserTransaction and TransactionManager
    @Bean
    public JtaTransactionManager customJtaTransactionManager(
            UserTransaction userTransaction,
            TransactionManager transactionManager) {

        JtaTransactionManager txManager = new JtaTransactionManager();
        txManager.setUserTransaction(userTransaction);
        txManager.setTransactionManager(transactionManager);
        txManager.setAllowCustomIsolationLevels(true);
        return txManager;
    }

    // With custom JNDI names
    @Bean
    public JtaTransactionManager jndiBasedJtaTransactionManager() {
        JtaTransactionManager txManager = new JtaTransactionManager();
        txManager.setUserTransactionName("java:comp/env/UserTransaction");
        txManager.setTransactionManagerName("java:comp/env/TransactionManager");
        return txManager;
    }
}

AbstractPlatformTransactionManager

Abstract base class for PlatformTransactionManager implementations. Provides the template method pattern for transaction management.

/**
 * Abstract base class for PlatformTransactionManager implementations.
 * Provides the transaction management template and common configuration.
 */
public abstract class AbstractPlatformTransactionManager
        implements PlatformTransactionManager, ConfigurableTransactionManager, Serializable {

    /** Synchronization always active */
    public static final int SYNCHRONIZATION_ALWAYS = 0;

    /** Synchronization only on actual transactions */
    public static final int SYNCHRONIZATION_ON_ACTUAL_TRANSACTION = 1;

    /** No synchronization */
    public static final int SYNCHRONIZATION_NEVER = 2;

    /**
     * Set when transaction synchronizations should be activated.
     * Default is SYNCHRONIZATION_ALWAYS.
     */
    public void setTransactionSynchronization(int transactionSynchronization);

    /**
     * Set the default timeout in seconds.
     * Default is -1 (no timeout).
     */
    public void setDefaultTimeout(int defaultTimeout);

    /**
     * Set whether nested transactions are allowed.
     * Default is false.
     */
    public void setNestedTransactionAllowed(boolean nestedTransactionAllowed);

    /**
     * Set whether existing transactions should be validated before participating.
     * Default is false.
     */
    public void setValidateExistingTransaction(boolean validateExistingTransaction);

    /**
     * Set whether to globally mark an existing transaction as rollback-only
     * after a participating transaction failed.
     * Default is true.
     */
    public void setGlobalRollbackOnParticipationFailure(
        boolean globalRollbackOnParticipationFailure
    );

    /**
     * Set whether to fail early on commit if the transaction has been
     * marked rollback-only globally.
     * Default is false.
     */
    public void setFailEarlyOnGlobalRollbackOnly(boolean failEarlyOnGlobalRollbackOnly);

    /**
     * Set whether to rollback on commit failure.
     * Default is false.
     */
    public void setRollbackOnCommitFailure(boolean rollbackOnCommitFailure);

    /**
     * Set transaction execution listeners.
     */
    public void setTransactionExecutionListeners(
        Collection<TransactionExecutionListener> listeners
    );

    // Template methods to be implemented by subclasses

    /**
     * Return the current transaction object.
     */
    protected abstract Object doGetTransaction() throws TransactionException;

    /**
     * Check if the given transaction object indicates an existing transaction.
     */
    protected abstract boolean isExistingTransaction(Object transaction)
            throws TransactionException;

    /**
     * Begin a new transaction with the given definition.
     */
    protected abstract void doBegin(
        Object transaction,
        TransactionDefinition definition
    ) throws TransactionException;

    /**
     * Perform an actual commit of the given transaction.
     */
    protected abstract void doCommit(DefaultTransactionStatus status)
            throws TransactionException;

    /**
     * Perform an actual rollback of the given transaction.
     */
    protected abstract void doRollback(DefaultTransactionStatus status)
            throws TransactionException;

    /**
     * Suspend the resources of the current transaction (optional).
     */
    protected Object doSuspend(Object transaction) throws TransactionException;

    /**
     * Resume the resources of the current transaction (optional).
     */
    protected void doResume(Object transaction, Object suspendedResources)
            throws TransactionException;

    /**
     * Set the given transaction rollback-only (optional).
     */
    protected void doSetRollbackOnly(DefaultTransactionStatus status)
            throws TransactionException;

    /**
     * Clean up after completion (optional).
     */
    protected void doCleanupAfterCompletion(Object transaction);
}

Usage Example (Custom Transaction Manager):

import org.springframework.transaction.support.AbstractPlatformTransactionManager;
import org.springframework.transaction.support.DefaultTransactionStatus;

public class CustomTransactionManager extends AbstractPlatformTransactionManager {

    private final ResourceManager resourceManager;

    public CustomTransactionManager(ResourceManager resourceManager) {
        this.resourceManager = resourceManager;
        setNestedTransactionAllowed(true);
        setDefaultTimeout(30);
    }

    @Override
    protected Object doGetTransaction() {
        CustomTransactionObject txObject = new CustomTransactionObject();
        txObject.setResourceHolder(resourceManager.getResourceHolder());
        return txObject;
    }

    @Override
    protected boolean isExistingTransaction(Object transaction) {
        CustomTransactionObject txObject = (CustomTransactionObject) transaction;
        return txObject.hasTransaction();
    }

    @Override
    protected void doBegin(Object transaction, TransactionDefinition definition) {
        CustomTransactionObject txObject = (CustomTransactionObject) transaction;
        resourceManager.beginTransaction(
            definition.getIsolationLevel(),
            definition.getTimeout()
        );
        txObject.setNewTransaction(true);
    }

    @Override
    protected void doCommit(DefaultTransactionStatus status) {
        CustomTransactionObject txObject = (CustomTransactionObject) status.getTransaction();
        resourceManager.commit();
    }

    @Override
    protected void doRollback(DefaultTransactionStatus status) {
        CustomTransactionObject txObject = (CustomTransactionObject) status.getTransaction();
        resourceManager.rollback();
    }

    @Override
    protected void doCleanupAfterCompletion(Object transaction) {
        CustomTransactionObject txObject = (CustomTransactionObject) transaction;
        resourceManager.releaseConnection();
    }
}

ConfigurableTransactionManager

Configuration interface for transaction managers supporting execution listeners.

/**
 * Configuration interface for transaction manager implementations.
 * Allows for registering transaction execution listeners.
 */
public interface ConfigurableTransactionManager extends TransactionManager {

    /**
     * Set transaction execution listeners for this transaction manager.
     */
    void setTransactionExecutionListeners(
        Collection<TransactionExecutionListener> listeners
    );

    /**
     * Get the transaction execution listeners for this transaction manager.
     */
    Collection<TransactionExecutionListener> getTransactionExecutionListeners();

    /**
     * Add a transaction execution listener.
     */
    default void addListener(TransactionExecutionListener listener);
}

Usage Example:

@Configuration
public class TransactionListenerConfig {

    @Bean
    public PlatformTransactionManager transactionManager() {
        JtaTransactionManager txManager = new JtaTransactionManager();

        // Add transaction execution listener
        txManager.addListener(new TransactionExecutionListener() {
            @Override
            public void beforeBegin(TransactionExecution transaction) {
                logger.info("Transaction starting: {}", transaction.getTransactionName());
            }

            @Override
            public void afterCommit(TransactionExecution transaction, Throwable commitFailure) {
                if (commitFailure == null) {
                    logger.info("Transaction committed successfully");
                } else {
                    logger.error("Transaction commit failed", commitFailure);
                }
            }
        });

        return txManager;
    }
}

TransactionExecutionListener

Callback interface for monitoring transaction lifecycle events.

/**
 * Callback interface for stateless listening to transaction creation/completion.
 * Allows monitoring of transaction lifecycle events.
 */
public interface TransactionExecutionListener {

    /**
     * Called before a new transaction begins.
     */
    default void beforeBegin(TransactionExecution transaction);

    /**
     * Called after a new transaction has begun, or after begin failure.
     */
    default void afterBegin(TransactionExecution transaction, Throwable beginFailure);

    /**
     * Called before transaction commit.
     */
    default void beforeCommit(TransactionExecution transaction);

    /**
     * Called after transaction commit (success or failure).
     */
    default void afterCommit(TransactionExecution transaction, Throwable commitFailure);

    /**
     * Called before transaction rollback.
     */
    default void beforeRollback(TransactionExecution transaction);

    /**
     * Called after transaction rollback (success or failure).
     */
    default void afterRollback(TransactionExecution transaction, Throwable rollbackFailure);
}

Usage Example:

public class MetricsTransactionListener implements TransactionExecutionListener {

    private final MeterRegistry meterRegistry;

    public MetricsTransactionListener(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
    }

    @Override
    public void afterCommit(TransactionExecution transaction, Throwable commitFailure) {
        if (commitFailure == null) {
            meterRegistry.counter("transactions.committed").increment();
        } else {
            meterRegistry.counter("transactions.commit.failed").increment();
        }
    }

    @Override
    public void afterRollback(TransactionExecution transaction, Throwable rollbackFailure) {
        meterRegistry.counter("transactions.rolled.back").increment();
    }
}

ResourceTransactionManager

Extended interface for transaction managers with resource awareness.

/**
 * Extension of PlatformTransactionManager for resource-specific transaction management.
 */
public interface ResourceTransactionManager extends PlatformTransactionManager {

    /**
     * Return the resource factory that this transaction manager operates on.
     * For example, a JDBC DataSource or a JMS ConnectionFactory.
     */
    Object getResourceFactory();
}

Usage Example:

@Service
public class DataSourceAwareService {

    private final ResourceTransactionManager transactionManager;

    public DataSourceAwareService(ResourceTransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }

    public void performOperation() {
        // Get the underlying DataSource
        DataSource dataSource = (DataSource) transactionManager.getResourceFactory();

        // Use transaction manager
        TransactionTemplate template = new TransactionTemplate(transactionManager);
        template.executeWithoutResult(status -> {
            // Execute operations
        });
    }
}

Common Patterns

Multiple Transaction Managers

@Configuration
@EnableTransactionManagement
public class MultipleTransactionManagersConfig {

    @Bean(name = "orderTransactionManager")
    @Primary
    public PlatformTransactionManager orderTransactionManager() {
        return new DataSourceTransactionManager(orderDataSource());
    }

    @Bean(name = "customerTransactionManager")
    public PlatformTransactionManager customerTransactionManager() {
        return new DataSourceTransactionManager(customerDataSource());
    }

    @Bean
    public DataSource orderDataSource() {
        // Configure order database
        return new HikariDataSource();
    }

    @Bean
    public DataSource customerDataSource() {
        // Configure customer database
        return new HikariDataSource();
    }
}

@Service
public class MultiDbService {

    // Use specific transaction manager
    @Transactional("orderTransactionManager")
    public void saveOrder(Order order) {
        orderRepository.save(order);
    }

    @Transactional("customerTransactionManager")
    public void saveCustomer(Customer customer) {
        customerRepository.save(customer);
    }
}

JTA for Distributed Transactions

@Configuration
public class DistributedTransactionConfig {

    @Bean
    public JtaTransactionManager jtaTransactionManager() {
        JtaTransactionManager txManager = new JtaTransactionManager();

        // Configure for distributed transactions
        txManager.setUserTransactionName("java:comp/UserTransaction");
        txManager.setTransactionManagerName("java:comp/TransactionManager");

        // Allow custom isolation levels if supported
        txManager.setAllowCustomIsolationLevels(true);

        return txManager;
    }

    @Bean
    public DataSource xaDataSource1() {
        // XA-capable data source
        return configureXaDataSource("db1");
    }

    @Bean
    public DataSource xaDataSource2() {
        // XA-capable data source
        return configureXaDataSource("db2");
    }
}

@Service
public class DistributedTransactionService {

    @Transactional
    public void performDistributedTransaction() {
        // Operations span multiple XA resources
        dataSource1Repository.save(entity1);
        dataSource2Repository.save(entity2);
        jmsTemplate.send(message);

        // All commit or rollback together
    }
}

Custom Transaction Manager Configuration

@Configuration
public class CustomTxManagerConfig {

    @Bean
    public PlatformTransactionManager transactionManager() {
        JtaTransactionManager txManager = new JtaTransactionManager();

        // Configure synchronization behavior
        txManager.setTransactionSynchronization(
            AbstractPlatformTransactionManager.SYNCHRONIZATION_ON_ACTUAL_TRANSACTION
        );

        // Set default timeout
        txManager.setDefaultTimeout(60);

        // Configure nested transaction support
        txManager.setNestedTransactionAllowed(false);

        // Validate existing transactions before participating
        txManager.setValidateExistingTransaction(true);

        // Global rollback on participation failure
        txManager.setGlobalRollbackOnParticipationFailure(true);

        // Fail early on global rollback
        txManager.setFailEarlyOnGlobalRollbackOnly(true);

        // Rollback on commit failure
        txManager.setRollbackOnCommitFailure(true);

        return txManager;
    }
}

Notes

  • PlatformTransactionManager is the central abstraction for all transaction managers
  • Most applications use a single transaction manager bean
  • For multiple data sources, define multiple transaction managers with different bean names
  • JtaTransactionManager is required for distributed transactions (XA)
  • Use @Primary annotation when having multiple transaction managers to indicate the default
  • Transaction managers are thread-safe and can be shared
  • Custom transaction managers should extend AbstractPlatformTransactionManager
  • Resource-specific transaction managers (JDBC, JPA, Hibernate) are provided by their respective Spring modules
  • Transaction execution listeners are useful for monitoring, metrics, and auditing