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

org.mule.transaction.TransactionTemplate Maven / Gradle / Ivy

There is a newer version: 3.9.0
Show newest version
/*
 * $Id: TransactionTemplate.java 23522 2011-12-21 19:47:19Z pablo.lagreca $
 * --------------------------------------------------------------------------------------
 * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 *
 * The software in this package is published under the terms of the CPAL v1.0
 * license, a copy of which has been included with this distribution in the
 * LICENSE.txt file.
 */

package org.mule.transaction;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.mule.api.MessagingException;
import org.mule.api.MuleContext;
import org.mule.api.MuleEvent;
import org.mule.api.transaction.*;
import org.mule.config.i18n.CoreMessages;

public class TransactionTemplate
{
    private static final Log logger = LogFactory.getLog(TransactionTemplate.class);
    private final TransactionConfig config;
    private final MuleContext context;
    private TransactionInterceptor transactionInterceptor;

    TransactionTemplate(MuleContext context, TransactionConfig config)
    {
        this.config = config;
        this.context = context;
    }

    /**
     * Use {@link org.mule.transaction.TransactionTemplateFactory} instead
     */
    @Deprecated
    public TransactionTemplate(TransactionConfig config, MuleContext context)
    {
        this(config, context, false);
    }

    /**
     * Use {@link org.mule.transaction.TransactionTemplateFactory} instead
     */
    @Deprecated
    public TransactionTemplate(TransactionConfig config, MuleContext context, boolean manageExceptions)
    {
        this.config = config;
        this.context = context;
        this.transactionInterceptor = new ExecuteCallbackInterceptor();
        if (manageExceptions)
        {
            this.transactionInterceptor = new HandleExceptionInterceptor(transactionInterceptor);
        }
        if (config != null && config.getAction() != TransactionConfig.ACTION_INDIFFERENT)
        {
            this.transactionInterceptor = new ExternalTransactionInterceptor(
                        new ValidateTransactionalStateInterceptor(
                                new SuspendXaTransactionInterceptor(
                                        new ResolveTransactionInterceptor(
                                                new BeginTransactionInterceptor(this.transactionInterceptor)))));
        }
    }

    TransactionTemplate(MuleContext muleContext)
    {
        this.context = muleContext;
        this.config = null;
    }

    void setTransactionInterceptor(TransactionInterceptor transactionInterceptor)
    {
        this.transactionInterceptor = transactionInterceptor;
    }

    public T execute(TransactionCallback callback) throws Exception
    {
        return transactionInterceptor.execute(callback);
    }

    public class HandleExceptionInterceptor implements TransactionInterceptor
    {
        public TransactionInterceptor next;

        public HandleExceptionInterceptor(TransactionInterceptor next)
        {
            this.next = next;
        }

        @Override
        public T execute(TransactionCallback callback) throws Exception
        {
            try
            {
                return next.execute(callback);
            }
            catch (MessagingException e)
            {
                T result = (T) e.getEvent().getFlowConstruct().getExceptionListener().handleException(e, e.getEvent());
                e.setProcessedEvent((MuleEvent) result);
                throw e;
            }
            catch (Exception e)
            {
                throw e;
            }
        }
    }

    public class ExternalTransactionInterceptor implements TransactionInterceptor
    {
        public TransactionInterceptor next;

        public ExternalTransactionInterceptor(TransactionInterceptor next)
        {
            this.next = next;
        }

        @Override
        public T execute(TransactionCallback callback) throws Exception
        {
            Transaction joinedExternal = null;
            Transaction tx = TransactionCoordination.getInstance().getTransaction();
            try
            {
                if (tx == null && context != null && config != null && config.isInteractWithExternal())
                {

                    TransactionFactory tmFactory = config.getFactory();
                    if (tmFactory instanceof ExternalTransactionAwareTransactionFactory)
                    {
                        ExternalTransactionAwareTransactionFactory externalTransactionFactory =
                            (ExternalTransactionAwareTransactionFactory) tmFactory;
                        joinedExternal = tx = externalTransactionFactory.joinExternalTransaction(context);
                    }
                }
                return next.execute(callback);
            }
            finally
            {
                if (joinedExternal != null)
                {
                    TransactionCoordination.getInstance().unbindTransaction(joinedExternal);
                }
            }
        }
    }

    public class SuspendXaTransactionInterceptor implements TransactionInterceptor
    {
        public TransactionInterceptor next;

        public SuspendXaTransactionInterceptor(TransactionInterceptor next)
        {
            this.next = next;
        }

        @Override
        public T execute(TransactionCallback callback) throws Exception
        {
            Transaction suspendedXATx = null;
            Transaction tx = TransactionCoordination.getInstance().getTransaction();
            byte action = config.getAction();
            if ((action == TransactionConfig.ACTION_NONE || action == TransactionConfig.ACTION_ALWAYS_BEGIN)
                   && tx != null && tx.isXA())
            {
                if (logger.isDebugEnabled())
                {
                    logger.debug("suspending XA tx " + action + ", " + "current TX: " + tx);
                }
                suspendedXATx = tx;
                suspendXATransaction(suspendedXATx);
            }
            T result = next.execute(callback);
            if (suspendedXATx != null)
            {
                resumeXATransaction(suspendedXATx);
            }
            return result;
        }
    }

    public class ValidateTransactionalStateInterceptor implements TransactionInterceptor
    {
        public TransactionInterceptor next;

        public ValidateTransactionalStateInterceptor(TransactionInterceptor next)
        {
            this.next = next;
        }

        @Override
        public T execute(TransactionCallback callback) throws Exception
        {
            Transaction tx = TransactionCoordination.getInstance().getTransaction();
            if (config.getAction() == TransactionConfig.ACTION_NEVER && tx != null)
            {
                throw new IllegalTransactionStateException(
                    CoreMessages.transactionAvailableButActionIs("Never"));
            }
            else if (config.getAction() == TransactionConfig.ACTION_ALWAYS_JOIN && tx == null)
            {
                throw new IllegalTransactionStateException(
                    CoreMessages.transactionNotAvailableButActionIs("Always Join"));
            }
            return this.next.execute(callback);
        }
    }

    public class ResolveTransactionInterceptor implements TransactionInterceptor
    {
        public TransactionInterceptor next;

        public ResolveTransactionInterceptor(TransactionInterceptor next)
        {
            this.next = next;
        }

        @Override
        public T execute(TransactionCallback callback) throws Exception
        {
            byte action = config.getAction();
            Transaction transactionBeforeTemplate = TransactionCoordination.getInstance().getTransaction();
            if ((action == TransactionConfig.ACTION_NONE || action == TransactionConfig.ACTION_ALWAYS_BEGIN)
                       && transactionBeforeTemplate != null)
            {
                if (logger.isDebugEnabled())
                {
                    logger.debug(action + ", " + "current TX: " + transactionBeforeTemplate);
                }

                resolveTransaction(transactionBeforeTemplate);
            }
            T result = next.execute(callback);
            Transaction currentTransaction = TransactionCoordination.getInstance().getTransaction();
            if (currentTransaction != null && (config.getAction() == TransactionConfig.ACTION_ALWAYS_BEGIN || (config.getAction() == TransactionConfig.ACTION_BEGIN_OR_JOIN && transactionBeforeTemplate == null)))
            {
                resolveTransaction(currentTransaction);
            }
            return result;
        }
    }

    public class BeginTransactionInterceptor implements TransactionInterceptor
    {
        public TransactionInterceptor next;

        public BeginTransactionInterceptor(TransactionInterceptor next)
        {
            this.next = next;
        }

        @Override
        public T execute(TransactionCallback callback) throws Exception
        {
            byte action = config.getAction();
            boolean transactionStarted = false;
            Transaction tx = TransactionCoordination.getInstance().getTransaction();
            if (action == TransactionConfig.ACTION_ALWAYS_BEGIN
                || (action == TransactionConfig.ACTION_BEGIN_OR_JOIN && tx == null))
            {
                logger.debug("Beginning transaction");
                tx = config.getFactory().beginTransaction(context);
                transactionStarted = true;
                logger.debug("Transaction successfully started: " + tx);
            }
            T result = next.execute(callback);
            Transaction transaction = TransactionCoordination.getInstance().getTransaction();
            if (transactionStarted && transaction != null)
            {
                resolveTransaction(transaction);
            }
            return result;
        }
    }

    public class ExecuteCallbackInterceptor implements TransactionInterceptor
    {

        @Override
        public T execute(TransactionCallback callback) throws Exception
        {
            return callback.doInTransaction();
        }
    }

    public interface TransactionInterceptor
    {
        T execute(TransactionCallback callback) throws Exception;
    }

    protected void resolveTransaction(Transaction tx) throws TransactionException
    {
        TransactionCoordination.getInstance().resolveTransaction();
    }

    protected void suspendXATransaction(Transaction tx) throws TransactionException
    {
        TransactionCoordination.getInstance().suspendCurrentTransaction();
    }

    protected void resumeXATransaction(Transaction tx) throws TransactionException
    {
        TransactionCoordination.getInstance().resumeSuspendedTransaction();
    }

}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy