/** {@inheritDoc} */
  @Override
  public void beforeProcess() throws Throwable {
    // prepare execution context
    AuthenticationUtil.pushAuthentication();
    AuthenticationUtil.setFullyAuthenticatedUser(this.fullyAuthenticatedUser);
    if (this.runAsUser != null && !this.runAsUser.equals(this.fullyAuthenticatedUser)) {
      AuthenticationUtil.setRunAsUser(this.runAsUser);
    }

    I18NUtil.setLocale(this.locale);
    if (this.contentLocale != null) {
      I18NUtil.setContentLocale(this.contentLocale);
    }

    try {
      try {
        super.doBeforeProcess();
      } catch (final WrappedException ex) {
        // super should already handle unwrap runtime exceptions
        final Throwable wrappedException = ex.getWrappedException();
        if (wrappedException instanceof RuntimeException) {
          // super should have handled this
          throw (RuntimeException) wrappedException;
        }
        throw new AlfrescoRuntimeException(wrappedException.getMessage(), wrappedException);
      } catch (final Throwable ex) {
        throw new AlfrescoRuntimeException(ex.getMessage(), ex);
      }
    } catch (final Throwable ex) {
      /*
       * The TxnCallback does not propagate non-retryable exceptions to the retrying transaction handler. Some exceptions may be
       * caused by execution of the provided script callback without passing through a service with its transaction interceptor which
       * would mark the transaction for rollback. We have to mark the transaction for rollback manually otherwise we end up with
       * commits of partial changes from the batch. (rollback on any exception is the default behaviour of Alfresco
       * SpringAwareUserTransaction)
       */

      final RuleBasedTransactionAttribute transactionAttribute =
          new RuleBasedTransactionAttribute();
      transactionAttribute.setReadOnly(true);
      transactionAttribute.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);

      // this never creates a new "real" transaction due to our propagation behavior
      final TransactionStatus transaction = this.txnManager.getTransaction(transactionAttribute);
      try {
        if (!transaction.isRollbackOnly()) {
          LOGGER.debug(
              "Marking transaction as rollback-only due to exception during batch processing", ex);
          transaction.setRollbackOnly();
        }
      } finally {
        // this never actually commits a "real" transaction - it just clears transaction
        // synchronizations
        this.txnManager.commit(transaction);
      }

      throw ex;
    }
  }
  /** {@inheritDoc} */
  @Override
  public void process(final Object entry) throws Throwable {
    try {
      try {
        super.doProcess(entry);
      } catch (final WrappedException ex) {
        // super should already handle unwrap runtime exceptions
        final Throwable wrappedException = ex.getWrappedException();
        if (wrappedException instanceof RuntimeException) {
          // super should have handled this
          throw (RuntimeException) wrappedException;
        }
        throw new AlfrescoRuntimeException(wrappedException.getMessage(), wrappedException);
      } catch (final Throwable ex) {
        throw new AlfrescoRuntimeException(ex.getMessage(), ex);
      }
    } catch (final Throwable ex) {
      /*
       * The TxnCallback does not propagate non-retryable exceptions to the retrying transaction handler. Some exceptions may be
       * caused by execution of the provided script callback without passing through a service with its transaction interceptor which
       * would mark the transaction for rollback. We have to mark the transaction for rollback manually otherwise we end up with
       * commits of partial changes from the batch. (rollback on any exception is the default behaviour of Alfresco
       * SpringAwareUserTransaction)
       */

      final RuleBasedTransactionAttribute transactionAttribute =
          new RuleBasedTransactionAttribute();
      transactionAttribute.setReadOnly(true);
      transactionAttribute.setPropagationBehavior(TransactionDefinition.PROPAGATION_MANDATORY);

      final TransactionStatus transaction = this.txnManager.getTransaction(transactionAttribute);
      if (!transaction.isRollbackOnly()) {
        LOGGER.debug(
            "Marking transaction as rollback-only due to exception during batch processing", ex);
        transaction.setRollbackOnly();
      }

      throw ex;
    }
  }