All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.molgenis.data.postgresql.transaction.PostgreSqlTransactionManager Maven / Gradle / Ivy

There is a newer version: 8.4.5
Show newest version
package org.molgenis.data.postgresql.transaction;

import static java.lang.String.format;
import static java.util.Objects.requireNonNull;

import java.util.ArrayList;
import java.util.List;
import javax.sql.DataSource;
import org.apache.commons.logging.LogFactory;
import org.molgenis.data.populate.IdGenerator;
import org.molgenis.data.transaction.MolgenisTransaction;
import org.molgenis.data.transaction.TransactionConstants;
import org.molgenis.data.transaction.TransactionExceptionTranslator;
import org.molgenis.data.transaction.TransactionExceptionTranslatorRegistry;
import org.molgenis.data.transaction.TransactionListener;
import org.molgenis.data.transaction.TransactionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.support.DefaultTransactionStatus;
import org.springframework.transaction.support.TransactionSynchronizationManager;

/**
 * TransactionManager used by Molgenis.
 *
 * 

TransactionListeners can be registered and will be notified on transaction begin, commit and * rollback of transactions that are not readonly. * *

Each transaction is given a unique transaction id. */ @SuppressWarnings("squid:S1948") // The transactionmanager will never be serialized public class PostgreSqlTransactionManager extends DataSourceTransactionManager implements TransactionManager { private static final long serialVersionUID = 1L; private static final Logger LOG = LoggerFactory.getLogger(PostgreSqlTransactionManager.class); private final IdGenerator idGenerator; private final List transactionListeners = new ArrayList<>(); private final TransactionExceptionTranslatorRegistry transactionExceptionTranslatorRegistry; public PostgreSqlTransactionManager( IdGenerator idGenerator, DataSource dataSource, TransactionExceptionTranslatorRegistry transactionExceptionTranslatorRegistry) { super(dataSource); super.logger = LogFactory.getLog(DataSourceTransactionManager.class); setNestedTransactionAllowed(false); this.idGenerator = idGenerator; this.transactionExceptionTranslatorRegistry = requireNonNull(transactionExceptionTranslatorRegistry); } @Override public synchronized void addTransactionListener(TransactionListener transactionListener) { transactionListeners.add(transactionListener); } @Override protected Object doGetTransaction() { Object dataSourceTransactionManager = super.doGetTransaction(); String id; if (TransactionSynchronizationManager.hasResource( TransactionConstants.TRANSACTION_ID_RESOURCE_NAME)) { id = (String) TransactionSynchronizationManager.getResource( TransactionConstants.TRANSACTION_ID_RESOURCE_NAME); } else { id = idGenerator.generateId().toLowerCase(); } return new MolgenisTransaction(id, dataSourceTransactionManager); } @Override protected void doBegin(Object transaction, TransactionDefinition definition) { MolgenisTransaction molgenisTransaction = (MolgenisTransaction) transaction; if (LOG.isDebugEnabled()) { LOG.debug("Start transaction [{}]", molgenisTransaction.getId()); } super.doBegin(molgenisTransaction.getDataSourceTransaction(), definition); if (!definition.isReadOnly()) { TransactionSynchronizationManager.bindResource( TransactionConstants.TRANSACTION_ID_RESOURCE_NAME, molgenisTransaction.getId()); transactionListeners.forEach(j -> j.transactionStarted(molgenisTransaction.getId())); } } @Override protected void doCommit(DefaultTransactionStatus status) { MolgenisTransaction transaction = (MolgenisTransaction) status.getTransaction(); if (LOG.isDebugEnabled()) { LOG.debug("Commit transaction [{}]", transaction.getId()); } DefaultTransactionStatus jpaTransactionStatus = new DefaultTransactionStatus( transaction.getDataSourceTransaction(), status.isNewTransaction(), status.isNewSynchronization(), status.isReadOnly(), status.isDebug(), status.getSuspendedResources()); if (!status.isReadOnly()) { transactionListeners.forEach(j -> j.commitTransaction(transaction.getId())); } try { super.doCommit(jpaTransactionStatus); } catch (TransactionException e) { throw translateTransactionException(e); } if (!status.isReadOnly()) { transactionListeners.forEach(j -> j.afterCommitTransaction(transaction.getId())); } } @Override protected void doRollback(DefaultTransactionStatus status) { MolgenisTransaction transaction = (MolgenisTransaction) status.getTransaction(); if (LOG.isDebugEnabled()) { LOG.debug("Rollback transaction [{}]", transaction.getId()); } DefaultTransactionStatus jpaTransactionStatus = new DefaultTransactionStatus( transaction.getDataSourceTransaction(), status.isNewTransaction(), status.isNewSynchronization(), status.isReadOnly(), status.isDebug(), status.getSuspendedResources()); if (!status.isReadOnly()) { transactionListeners.forEach(j -> j.rollbackTransaction(transaction.getId())); } super.doRollback(jpaTransactionStatus); } @Override protected void doSetRollbackOnly(DefaultTransactionStatus status) { MolgenisTransaction transaction = (MolgenisTransaction) status.getTransaction(); DefaultTransactionStatus jpaTransactionStatus = new DefaultTransactionStatus( transaction.getDataSourceTransaction(), status.isNewTransaction(), status.isNewSynchronization(), status.isReadOnly(), status.isDebug(), status.getSuspendedResources()); super.doSetRollbackOnly(jpaTransactionStatus); } @Override protected boolean isExistingTransaction(Object transaction) { return super.isExistingTransaction( ((MolgenisTransaction) transaction).getDataSourceTransaction()); } @Override protected void doCleanupAfterCompletion(Object transaction) { MolgenisTransaction molgenisTransaction = (MolgenisTransaction) transaction; if (LOG.isDebugEnabled()) { LOG.debug("Cleanup transaction [{}]", molgenisTransaction.getId()); } super.doCleanupAfterCompletion(molgenisTransaction.getDataSourceTransaction()); TransactionSynchronizationManager.unbindResourceIfPossible( TransactionConstants.TRANSACTION_ID_RESOURCE_NAME); transactionListeners.forEach(j -> j.doCleanupAfterCompletion(molgenisTransaction.getId())); } @Override protected Object doSuspend(Object transaction) { MolgenisTransaction molgenisTransaction = (MolgenisTransaction) transaction; return super.doSuspend(molgenisTransaction.getDataSourceTransaction()); } @Override protected void doResume(Object transaction, Object suspendedResources) { MolgenisTransaction molgenisTransaction = (MolgenisTransaction) transaction; super.doResume(molgenisTransaction.getDataSourceTransaction(), suspendedResources); } private RuntimeException translateTransactionException( TransactionException transactionException) { for (TransactionExceptionTranslator transactionExceptionTranslator : transactionExceptionTranslatorRegistry.getTransactionExceptionTranslators()) { RuntimeException translatedException = transactionExceptionTranslator.doTranslate(transactionException); if (translatedException != null) { return translatedException; } } throw new IllegalArgumentException( format("Unexpected exception class [%s]", transactionException.getClass().getSimpleName()), transactionException); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy