/** * Return a SavepointManager for the underlying transaction, if possible. * <p>Default implementation always throws a NestedTransactionNotSupportedException. * @throws org.springframework.transaction.NestedTransactionNotSupportedException * if the underlying transaction does not support savepoints */ protected SavepointManager getSavepointManager() { throw new NestedTransactionNotSupportedException("This transaction does not support savepoints"); }
/** * Constructor for HeuristicCompletionException. * @param outcomeState the outcome state of the transaction * @param cause the root cause from the transaction API in use */ public HeuristicCompletionException(int outcomeState, Throwable cause) { super("Heuristic completion: outcome state is " + getStateString(outcomeState), cause); this.outcomeState = outcomeState; }
/** * Release the savepoint that is held for the transaction. */ public void releaseHeldSavepoint() throws TransactionException { Object savepoint = getSavepoint(); if (savepoint == null) { throw new TransactionUsageException( "Cannot release savepoint - no savepoint associated with current transaction"); } getSavepointManager().releaseSavepoint(savepoint); setSavepoint(null); }
protected void startNewTransaction() throws TransactionException { this.transactionStatus = this.transactionManager.getTransaction(this.transactionDefinition); }
@Override protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException { status.setRollbackOnly(); } });
@Override public void rollback(TransactionStatus status) { delegate.rollback(status); }
@Override public void commit(TransactionStatus status) { delegate.commit(status); }
@Override protected void doBegin(Object transaction, TransactionDefinition definition) { JtaTransactionObject txObject = (JtaTransactionObject) transaction; try { doJtaBegin(txObject, definition); } catch (NotSupportedException | UnsupportedOperationException ex) { throw new NestedTransactionNotSupportedException( "JTA implementation does not support nested transactions", ex); } catch (SystemException ex) { throw new CannotCreateTransactionException("JTA failure on begin", ex); } }
@Test public void rollbackOnlyWithExistingTransaction() { TestTransactionManager tm = new TestTransactionManager(true, true); TransactionStatus status = tm.getTransaction(null); status.setRollbackOnly(); tm.commit(status); assertTrue("no begin", !tm.begin); assertTrue("no commit", !tm.commit); assertTrue("no rollback", !tm.rollback); assertTrue("triggered rollbackOnly", tm.rollbackOnly); }
@Override public int getIsolationLevel() { return this.targetDefinition.getIsolationLevel(); }
@Override public boolean isReadOnly() { return this.targetDefinition.isReadOnly(); }
protected ConnectionHolder getConnectionHolderForSavepoint() throws TransactionException { if (!isSavepointAllowed()) { throw new NestedTransactionNotSupportedException( "Transaction manager does not allow nested transactions"); } if (!hasConnectionHolder()) { throw new TransactionUsageException( "Cannot create nested transaction when not exposing a JDBC transaction"); } return getConnectionHolder(); }
@Override public int getTimeout() { return this.targetDefinition.getTimeout(); }
/** * Set the given transaction rollback-only. Only called on rollback * if the current transaction participates in an existing one. * <p>The default implementation throws an IllegalTransactionStateException, * assuming that participating in existing transactions is generally not * supported. Subclasses are of course encouraged to provide such support. * @param status the status representation of the transaction * @throws TransactionException in case of system errors */ protected void doSetRollbackOnly(DefaultTransactionStatus status) throws TransactionException { throw new IllegalTransactionStateException( "Participating in existing transactions is not supported - when 'isExistingTransaction' " + "returns true, appropriate 'doSetRollbackOnly' behavior must be provided"); }
@Override public int getPropagationBehavior() { return this.targetDefinition.getPropagationBehavior(); }
/** * Specify the default timeout that this transaction manager should apply * if there is no timeout specified at the transaction level, in seconds. * <p>Default is the underlying transaction infrastructure's default timeout, * e.g. typically 30 seconds in case of a JTA provider, indicated by the * {@code TransactionDefinition.TIMEOUT_DEFAULT} value. * @see org.springframework.transaction.TransactionDefinition#TIMEOUT_DEFAULT */ public final void setDefaultTimeout(int defaultTimeout) { if (defaultTimeout < TransactionDefinition.TIMEOUT_DEFAULT) { throw new InvalidTimeoutException("Invalid default timeout", defaultTimeout); } this.defaultTimeout = defaultTimeout; }
@Override protected void doRollback(DefaultTransactionStatus status) { super.doRollback(status); throw tex; } };
protected TestTransactionManager(boolean existingTransaction, boolean canCreateTransaction) { this.existingTransaction = existingTransaction; this.canCreateTransaction = canCreateTransaction; setTransactionSynchronization(SYNCHRONIZATION_NEVER); }
@Override protected void doInTransactionWithoutResult(TransactionStatus status) { status.setRollbackOnly(); } });
/** * Roll back to the savepoint that is held for the transaction * and release the savepoint right afterwards. */ public void rollbackToHeldSavepoint() throws TransactionException { Object savepoint = getSavepoint(); if (savepoint == null) { throw new TransactionUsageException( "Cannot roll back to savepoint - no savepoint associated with current transaction"); } getSavepointManager().rollbackToSavepoint(savepoint); getSavepointManager().releaseSavepoint(savepoint); setSavepoint(null); }