Search in sources :

Example 1 with IllegalTransactionStateException

use of org.springframework.transaction.IllegalTransactionStateException in project spring-framework by spring-projects.

the class WebSphereUowTransactionManager method execute.

@Override
public <T> T execute(TransactionDefinition definition, TransactionCallback<T> callback) throws TransactionException {
    if (definition == null) {
        // Use defaults if no transaction definition given.
        definition = new DefaultTransactionDefinition();
    }
    if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
        throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
    }
    int pb = definition.getPropagationBehavior();
    boolean existingTx = (this.uowManager.getUOWStatus() != UOWSynchronizationRegistry.UOW_STATUS_NONE && this.uowManager.getUOWType() != UOWSynchronizationRegistry.UOW_TYPE_LOCAL_TRANSACTION);
    int uowType = UOWSynchronizationRegistry.UOW_TYPE_GLOBAL_TRANSACTION;
    boolean joinTx = false;
    boolean newSynch = false;
    if (existingTx) {
        if (pb == TransactionDefinition.PROPAGATION_NEVER) {
            throw new IllegalTransactionStateException("Transaction propagation 'never' but existing transaction found");
        }
        if (pb == TransactionDefinition.PROPAGATION_NESTED) {
            throw new NestedTransactionNotSupportedException("Transaction propagation 'nested' not supported for WebSphere UOW transactions");
        }
        if (pb == TransactionDefinition.PROPAGATION_SUPPORTS || pb == TransactionDefinition.PROPAGATION_REQUIRED || pb == TransactionDefinition.PROPAGATION_MANDATORY) {
            joinTx = true;
            newSynch = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
        } else if (pb == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
            uowType = UOWSynchronizationRegistry.UOW_TYPE_LOCAL_TRANSACTION;
            newSynch = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
        } else {
            newSynch = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
        }
    } else {
        if (pb == TransactionDefinition.PROPAGATION_MANDATORY) {
            throw new IllegalTransactionStateException("Transaction propagation 'mandatory' but no existing transaction found");
        }
        if (pb == TransactionDefinition.PROPAGATION_SUPPORTS || pb == TransactionDefinition.PROPAGATION_NOT_SUPPORTED || pb == TransactionDefinition.PROPAGATION_NEVER) {
            uowType = UOWSynchronizationRegistry.UOW_TYPE_LOCAL_TRANSACTION;
            newSynch = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
        } else {
            newSynch = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
        }
    }
    boolean debug = logger.isDebugEnabled();
    if (debug) {
        logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
    }
    SuspendedResourcesHolder suspendedResources = (!joinTx ? suspend(null) : null);
    try {
        if (definition.getTimeout() > TransactionDefinition.TIMEOUT_DEFAULT) {
            this.uowManager.setUOWTimeout(uowType, definition.getTimeout());
        }
        if (debug) {
            logger.debug("Invoking WebSphere UOW action: type=" + uowType + ", join=" + joinTx);
        }
        UOWActionAdapter<T> action = new UOWActionAdapter<>(definition, callback, (uowType == UOWManager.UOW_TYPE_GLOBAL_TRANSACTION), !joinTx, newSynch, debug);
        this.uowManager.runUnderUOW(uowType, joinTx, action);
        if (debug) {
            logger.debug("Returned from WebSphere UOW action: type=" + uowType + ", join=" + joinTx);
        }
        return action.getResult();
    } catch (UOWException ex) {
        throw new TransactionSystemException("UOWManager transaction processing failed", ex);
    } catch (UOWActionException ex) {
        throw new TransactionSystemException("UOWManager threw unexpected UOWActionException", ex);
    } finally {
        if (suspendedResources != null) {
            resume(null, suspendedResources);
        }
    }
}
Also used : UOWActionException(com.ibm.wsspi.uow.UOWActionException) DefaultTransactionDefinition(org.springframework.transaction.support.DefaultTransactionDefinition) IllegalTransactionStateException(org.springframework.transaction.IllegalTransactionStateException) TransactionSystemException(org.springframework.transaction.TransactionSystemException) InvalidTimeoutException(org.springframework.transaction.InvalidTimeoutException) UOWException(com.ibm.wsspi.uow.UOWException) NestedTransactionNotSupportedException(org.springframework.transaction.NestedTransactionNotSupportedException)

Example 2 with IllegalTransactionStateException

use of org.springframework.transaction.IllegalTransactionStateException in project spring-framework by spring-projects.

the class WebSphereUowTransactionManagerTests method propagationNeverFailsInCaseOfExistingTransaction.

@Test
public void propagationNeverFailsInCaseOfExistingTransaction() {
    MockUOWManager manager = new MockUOWManager();
    manager.setUOWStatus(UOWManager.UOW_STATUS_ACTIVE);
    WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
    DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
    definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_NEVER);
    try {
        ptm.execute(definition, new TransactionCallback<String>() {

            @Override
            public String doInTransaction(TransactionStatus status) {
                return "result";
            }
        });
        fail("Should have thrown IllegalTransactionStateException");
    } catch (IllegalTransactionStateException ex) {
    // expected
    }
}
Also used : DefaultTransactionDefinition(org.springframework.transaction.support.DefaultTransactionDefinition) IllegalTransactionStateException(org.springframework.transaction.IllegalTransactionStateException) TransactionStatus(org.springframework.transaction.TransactionStatus) Test(org.junit.Test)

Example 3 with IllegalTransactionStateException

use of org.springframework.transaction.IllegalTransactionStateException in project spring-framework by spring-projects.

the class DataSourceTransactionManagerTests method testPropagationNeverWithExistingTransaction.

@Test
public void testPropagationNeverWithExistingTransaction() throws Exception {
    final TransactionTemplate tt = new TransactionTemplate(tm);
    tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
    boolean condition2 = !TransactionSynchronizationManager.hasResource(ds);
    assertThat(condition2).as("Hasn't thread connection").isTrue();
    boolean condition1 = !TransactionSynchronizationManager.isSynchronizationActive();
    assertThat(condition1).as("Synchronization not active").isTrue();
    assertThatExceptionOfType(IllegalTransactionStateException.class).isThrownBy(() -> tt.execute(new TransactionCallbackWithoutResult() {

        @Override
        protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
            assertThat(status.isNewTransaction()).as("Is new transaction").isTrue();
            tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NEVER);
            tt.execute(new TransactionCallbackWithoutResult() {

                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
                    fail("Should have thrown IllegalTransactionStateException");
                }
            });
            fail("Should have thrown IllegalTransactionStateException");
        }
    }));
    boolean condition = !TransactionSynchronizationManager.hasResource(ds);
    assertThat(condition).as("Hasn't thread connection").isTrue();
    verify(con).rollback();
    verify(con).close();
}
Also used : TransactionTemplate(org.springframework.transaction.support.TransactionTemplate) IllegalTransactionStateException(org.springframework.transaction.IllegalTransactionStateException) TransactionStatus(org.springframework.transaction.TransactionStatus) TransactionCallbackWithoutResult(org.springframework.transaction.support.TransactionCallbackWithoutResult) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 4 with IllegalTransactionStateException

use of org.springframework.transaction.IllegalTransactionStateException in project spring-framework by spring-projects.

the class HibernateTransactionManager method doBegin.

@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
    HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;
    if (txObject.hasConnectionHolder() && !txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
        throw new IllegalTransactionStateException("Pre-bound JDBC Connection found! HibernateTransactionManager does not support " + "running within DataSourceTransactionManager if told to manage the DataSource itself. " + "It is recommended to use a single HibernateTransactionManager for all transactions " + "on a single DataSource, no matter whether Hibernate or JDBC access.");
    }
    SessionImplementor session = null;
    try {
        if (!txObject.hasSessionHolder() || txObject.getSessionHolder().isSynchronizedWithTransaction()) {
            Interceptor entityInterceptor = getEntityInterceptor();
            Session newSession = (entityInterceptor != null ? obtainSessionFactory().withOptions().interceptor(entityInterceptor).openSession() : obtainSessionFactory().openSession());
            if (this.sessionInitializer != null) {
                this.sessionInitializer.accept(newSession);
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Opened new Session [" + newSession + "] for Hibernate transaction");
            }
            txObject.setSession(newSession);
        }
        session = txObject.getSessionHolder().getSession().unwrap(SessionImplementor.class);
        boolean holdabilityNeeded = this.allowResultAccessAfterCompletion && !txObject.isNewSession();
        boolean isolationLevelNeeded = (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT);
        if (holdabilityNeeded || isolationLevelNeeded || definition.isReadOnly()) {
            if (this.prepareConnection && ConnectionReleaseMode.ON_CLOSE.equals(session.getJdbcCoordinator().getLogicalConnection().getConnectionHandlingMode().getReleaseMode())) {
                // We're allowed to change the transaction settings of the JDBC Connection.
                if (logger.isDebugEnabled()) {
                    logger.debug("Preparing JDBC Connection of Hibernate Session [" + session + "]");
                }
                Connection con = session.connection();
                Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
                txObject.setPreviousIsolationLevel(previousIsolationLevel);
                txObject.setReadOnly(definition.isReadOnly());
                if (this.allowResultAccessAfterCompletion && !txObject.isNewSession()) {
                    int currentHoldability = con.getHoldability();
                    if (currentHoldability != ResultSet.HOLD_CURSORS_OVER_COMMIT) {
                        txObject.setPreviousHoldability(currentHoldability);
                        con.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT);
                    }
                }
                txObject.connectionPrepared();
            } else {
                // Not allowed to change the transaction settings of the JDBC Connection.
                if (isolationLevelNeeded) {
                    // We should set a specific isolation level but are not allowed to...
                    throw new InvalidIsolationLevelException("HibernateTransactionManager is not allowed to support custom isolation levels: " + "make sure that its 'prepareConnection' flag is on (the default) and that the " + "Hibernate connection release mode is set to ON_CLOSE.");
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("Not preparing JDBC Connection of Hibernate Session [" + session + "]");
                }
            }
        }
        if (definition.isReadOnly() && txObject.isNewSession()) {
            // Just set to MANUAL in case of a new Session for this transaction.
            session.setHibernateFlushMode(FlushMode.MANUAL);
            // As of 5.1, we're also setting Hibernate's read-only entity mode by default.
            session.setDefaultReadOnly(true);
        }
        if (!definition.isReadOnly() && !txObject.isNewSession()) {
            // We need AUTO or COMMIT for a non-read-only transaction.
            FlushMode flushMode = session.getHibernateFlushMode();
            if (FlushMode.MANUAL.equals(flushMode)) {
                session.setHibernateFlushMode(FlushMode.AUTO);
                txObject.getSessionHolder().setPreviousFlushMode(flushMode);
            }
        }
        Transaction hibTx;
        // Register transaction timeout.
        int timeout = determineTimeout(definition);
        if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
            // Use Hibernate's own transaction timeout mechanism on Hibernate 3.1+
            // Applies to all statements, also to inserts, updates and deletes!
            hibTx = session.getTransaction();
            hibTx.setTimeout(timeout);
            hibTx.begin();
        } else {
            // Open a plain Hibernate transaction without specified timeout.
            hibTx = session.beginTransaction();
        }
        // Add the Hibernate transaction to the session holder.
        txObject.getSessionHolder().setTransaction(hibTx);
        // Register the Hibernate Session's JDBC Connection for the DataSource, if set.
        if (getDataSource() != null) {
            ConnectionHolder conHolder = new ConnectionHolder(session::connection);
            if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
                conHolder.setTimeoutInSeconds(timeout);
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Exposing Hibernate transaction as JDBC [" + conHolder.getConnectionHandle() + "]");
            }
            TransactionSynchronizationManager.bindResource(getDataSource(), conHolder);
            txObject.setConnectionHolder(conHolder);
        }
        // Bind the session holder to the thread.
        if (txObject.isNewSessionHolder()) {
            TransactionSynchronizationManager.bindResource(obtainSessionFactory(), txObject.getSessionHolder());
        }
        txObject.getSessionHolder().setSynchronizedWithTransaction(true);
    } catch (Throwable ex) {
        if (txObject.isNewSession()) {
            try {
                if (session != null && session.getTransaction().getStatus() == TransactionStatus.ACTIVE) {
                    session.getTransaction().rollback();
                }
            } catch (Throwable ex2) {
                logger.debug("Could not rollback Session after failed transaction begin", ex);
            } finally {
                SessionFactoryUtils.closeSession(session);
                txObject.setSessionHolder(null);
            }
        }
        throw new CannotCreateTransactionException("Could not open Hibernate Session for transaction", ex);
    }
}
Also used : CannotCreateTransactionException(org.springframework.transaction.CannotCreateTransactionException) IllegalTransactionStateException(org.springframework.transaction.IllegalTransactionStateException) Connection(java.sql.Connection) InvalidIsolationLevelException(org.springframework.transaction.InvalidIsolationLevelException) FlushMode(org.hibernate.FlushMode) ConnectionHolder(org.springframework.jdbc.datasource.ConnectionHolder) Transaction(org.hibernate.Transaction) SessionImplementor(org.hibernate.engine.spi.SessionImplementor) Interceptor(org.hibernate.Interceptor) Session(org.hibernate.Session)

Example 5 with IllegalTransactionStateException

use of org.springframework.transaction.IllegalTransactionStateException in project spring-framework by spring-projects.

the class JpaTransactionManager method doBegin.

@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
    JpaTransactionObject txObject = (JpaTransactionObject) transaction;
    if (txObject.hasConnectionHolder() && !txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
        throw new IllegalTransactionStateException("Pre-bound JDBC Connection found! JpaTransactionManager does not support " + "running within DataSourceTransactionManager if told to manage the DataSource itself. " + "It is recommended to use a single JpaTransactionManager for all transactions " + "on a single DataSource, no matter whether JPA or JDBC access.");
    }
    try {
        if (txObject.getEntityManagerHolder() == null || txObject.getEntityManagerHolder().isSynchronizedWithTransaction()) {
            EntityManager newEm = createEntityManagerForTransaction();
            if (logger.isDebugEnabled()) {
                logger.debug("Opened new EntityManager [" + newEm + "] for JPA transaction");
            }
            txObject.setEntityManagerHolder(new EntityManagerHolder(newEm), true);
        }
        EntityManager em = txObject.getEntityManagerHolder().getEntityManager();
        // Delegate to JpaDialect for actual transaction begin.
        final int timeoutToUse = determineTimeout(definition);
        Object transactionData = getJpaDialect().beginTransaction(em, new DelegatingTransactionDefinition(definition) {

            @Override
            public int getTimeout() {
                return timeoutToUse;
            }
        });
        txObject.setTransactionData(transactionData);
        // Register transaction timeout.
        if (timeoutToUse != TransactionDefinition.TIMEOUT_DEFAULT) {
            txObject.getEntityManagerHolder().setTimeoutInSeconds(timeoutToUse);
        }
        // Register the JPA EntityManager's JDBC Connection for the DataSource, if set.
        if (getDataSource() != null) {
            ConnectionHandle conHandle = getJpaDialect().getJdbcConnection(em, definition.isReadOnly());
            if (conHandle != null) {
                ConnectionHolder conHolder = new ConnectionHolder(conHandle);
                if (timeoutToUse != TransactionDefinition.TIMEOUT_DEFAULT) {
                    conHolder.setTimeoutInSeconds(timeoutToUse);
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("Exposing JPA transaction as JDBC transaction [" + conHolder.getConnectionHandle() + "]");
                }
                TransactionSynchronizationManager.bindResource(getDataSource(), conHolder);
                txObject.setConnectionHolder(conHolder);
            } else {
                if (logger.isDebugEnabled()) {
                    logger.debug("Not exposing JPA transaction [" + em + "] as JDBC transaction because " + "JpaDialect [" + getJpaDialect() + "] does not support JDBC Connection retrieval");
                }
            }
        }
        // Bind the entity manager holder to the thread.
        if (txObject.isNewEntityManagerHolder()) {
            TransactionSynchronizationManager.bindResource(getEntityManagerFactory(), txObject.getEntityManagerHolder());
        }
        txObject.getEntityManagerHolder().setSynchronizedWithTransaction(true);
    } catch (TransactionException ex) {
        closeEntityManagerAfterFailedBegin(txObject);
        throw ex;
    } catch (Throwable ex) {
        closeEntityManagerAfterFailedBegin(txObject);
        throw new CannotCreateTransactionException("Could not open JPA EntityManager for transaction", ex);
    }
}
Also used : DelegatingTransactionDefinition(org.springframework.transaction.support.DelegatingTransactionDefinition) ConnectionHandle(org.springframework.jdbc.datasource.ConnectionHandle) CannotCreateTransactionException(org.springframework.transaction.CannotCreateTransactionException) IllegalTransactionStateException(org.springframework.transaction.IllegalTransactionStateException) ConnectionHolder(org.springframework.jdbc.datasource.ConnectionHolder) EntityManager(javax.persistence.EntityManager) CannotCreateTransactionException(org.springframework.transaction.CannotCreateTransactionException) TransactionException(org.springframework.transaction.TransactionException)

Aggregations

IllegalTransactionStateException (org.springframework.transaction.IllegalTransactionStateException)10 TransactionStatus (org.springframework.transaction.TransactionStatus)4 InvalidTimeoutException (org.springframework.transaction.InvalidTimeoutException)3 DefaultTransactionDefinition (org.springframework.transaction.support.DefaultTransactionDefinition)3 Test (org.junit.Test)2 Test (org.junit.jupiter.api.Test)2 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)2 ConnectionHolder (org.springframework.jdbc.datasource.ConnectionHolder)2 CannotCreateTransactionException (org.springframework.transaction.CannotCreateTransactionException)2 NestedTransactionNotSupportedException (org.springframework.transaction.NestedTransactionNotSupportedException)2 TransactionDefinition (org.springframework.transaction.TransactionDefinition)2 TransactionException (org.springframework.transaction.TransactionException)2 TransactionCallbackWithoutResult (org.springframework.transaction.support.TransactionCallbackWithoutResult)2 TransactionTemplate (org.springframework.transaction.support.TransactionTemplate)2 UOWActionException (com.ibm.wsspi.uow.UOWActionException)1 UOWException (com.ibm.wsspi.uow.UOWException)1 IOException (java.io.IOException)1 ObjectInputStream (java.io.ObjectInputStream)1 Serializable (java.io.Serializable)1 Connection (java.sql.Connection)1