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

io.ebeaninternal.api.ScopedTransaction Maven / Gradle / Ivy

There is a newer version: 15.8.1
Show newest version
package io.ebeaninternal.api;

import io.ebeaninternal.server.transaction.TransactionScopeManager;
import io.ebeaninternal.server.util.ArrayStack;

import javax.persistence.PersistenceException;

/**
 * Manage scoped (typically thread local) transactions.
 *
 * These can be nested and internally they are pushed and popped from a stack.
 */
public class ScopedTransaction extends SpiTransactionProxy {

  private final TransactionScopeManager manager;

  /**
   * Stack of 'nested' transactions.
   */
  private ArrayStack stack = new ArrayStack<>();

  private ScopeTrans current;

  /**
   * Flag set when we clear the thread scope (on commit/rollback or end).
   */
  private boolean scopeCleared;

  public ScopedTransaction(TransactionScopeManager manager) {
    this.manager = manager;
  }

  @Override
  public String toString() {
    return "ScopedTransaction[" + current + "]";
  }

  /**
   * Push the scope transaction.
   */
  public void push(ScopeTrans scopeTrans) {

    if (current != null) {
      stack.push(current);
    }
    current = scopeTrans;
    transaction = scopeTrans.getTransaction();
  }

  /**
   * Exiting an enhanced transactional method.
   */
  public void complete(Object returnOrThrowable, int opCode) {
    current.complete(returnOrThrowable, opCode);
    // no finally here for pop() as we come in here twice if an
    // error is thrown on commit (due to enhancement finally block)
    pop();
  }

  /**
   * Internal programmatic complete - finally block, try to commit.
   */
  public void complete() {
    try {
      current.complete();
    } finally {
      pop();
    }
  }

  private void clearScopeOnce() {
    if (!scopeCleared) {
      manager.set(null);
      scopeCleared = true;
    }
  }

  private boolean clearScope() {
    if (stack.isEmpty()) {
      clearScopeOnce();
      return true;
    }
    return false;
  }

  private void pop() {
    if (!clearScope()) {
      current = stack.pop();
      transaction = current.getTransaction();
    }
  }

  @Override
  public void end() throws PersistenceException {
    try {
      current.end();
    } finally {
      pop();
    }
  }

  @Override
  public void close() {
    end();
  }

  @Override
  public void commit() {
    try {
      current.commitTransaction();
    } finally {
      clearScope();
    }
  }

  @Override
  public void rollback() throws PersistenceException {
    try {
      current.rollback(null);
    } finally {
      clearScope();
    }
  }

  @Override
  public void rollback(Throwable e) throws PersistenceException {
    try {
      current.rollback(e);
    } finally {
      clearScope();
    }
  }

  @Override
  public void setRollbackOnly() {
    current.setRollbackOnly();
  }

  /**
   * Return the current transaction.
   */
  public SpiTransaction current() {
    return transaction;
  }

  /**
   * Rollback for Error.
   */
  public Error caughtError(Error e) {
    return current.caughtError(e);
  }

  /**
   * Maybe rollback based on TxScope rollback on settings.
   */
  public Exception caughtThrowable(Exception e) {
    return current.caughtThrowable(e);
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy