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

org.jboss.jbossts.txbridge.inbound.BridgeVolatileParticipant Maven / Gradle / Ivy

The newest version!
/*
   Copyright The Narayana Authors
   SPDX-License-Identifier: Apache-2.0
 */

package org.jboss.jbossts.txbridge.inbound;

import com.arjuna.ats.jta.utils.XAHelper;
import com.arjuna.wst.*;
import com.arjuna.ats.internal.jta.resources.spi.XATerminatorExtensions;
import com.arjuna.ats.internal.jta.transaction.arjunacore.jca.SubordinationManager;
import com.arjuna.ats.jta.utils.JTAHelper;
import org.jboss.jbossts.txbridge.utils.txbridgeLogger;

import javax.transaction.xa.Xid;
import jakarta.transaction.Status;

/**
 * Provides method call mapping between WS-AT Volatile Participant interface
 * and an underlying JTA subtransaction coordinator.
 *
 * @author [email protected], 2009-06-01
 */
public class BridgeVolatileParticipant implements Volatile2PCParticipant
{
    // no standard interface for driving Synchronization phases separately
    // in JCA, so we have to use proprietary API.
    private final XATerminatorExtensions xaTerminatorExtensions;

    private final String externalTxId;

    private final Xid xid;

    /**
     * Create a new WS-AT Volatile Participant which wraps the subordinate XA tx terminator.
     *
     * @param externalTxId the WS-AT Tx identifier
     * @param xid the Xid to use when driving the subordinate XA transaction.
     */
    BridgeVolatileParticipant(String externalTxId, Xid xid)
    {
        txbridgeLogger.logger.trace("BridgeVolatileParticipant.(TxId="+externalTxId+", Xid="+xid+")");

        this.xid = xid;
        this.externalTxId = externalTxId;
        this.xaTerminatorExtensions = (XATerminatorExtensions)SubordinationManager.getXATerminator();
    }

    /**
     * Perform beforeCompletion activities such as flushing cached state to stable store.
     *
     * @return an indication of whether it can prepare or not.
     * @see com.arjuna.wst.Vote
     */
    public Vote prepare() throws WrongStateException, SystemException
    {
        txbridgeLogger.logger.trace("BridgeVolatileParticipant.prepare(Xid="+xid+")");

        // Usually a VolatileParticipant would return Aborted to stop the tx in error cases. However, that
        // would mean rollback() would not be called on the instance returning Aborted, which would make it
        // hard to invoke afterCompletion on the subordinate. So we cheat a bit by using setRollbackOnly instead.
        // A slightly more efficient but less clear impl would be to have the same object implement both the Volatile
        // and Durable Participants and keep count of the number of prepare/rollback invocations to know
        // if being invoked as Volatile or Durable.

        InboundBridge inboundBridge = InboundBridgeManager.getInboundBridge(externalTxId);

        try
        {
            // TODO: check for rollbackOnly before bothering to invoke?
            // beforeCompletion should run in tx context.
            inboundBridge.start();

            if(!xaTerminatorExtensions.beforeCompletion(xid))
            {
                txbridgeLogger.i18NLogger.warn_ibvp_preparefailed(XAHelper.xidToString(xid), null);
                inboundBridge.setRollbackOnly();
            }

            return new Prepared();
        }
        catch(Exception e)
        {
            txbridgeLogger.i18NLogger.warn_ibvp_preparefailed(XAHelper.xidToString(xid), e);
            try
            {
                inboundBridge.setRollbackOnly();
            }
            catch(Exception e2)
            {
                txbridgeLogger.i18NLogger.warn_ibvp_setrollbackfailed(e2);
            }

            return new Prepared();
        }
        finally
        {
            try
            {
                inboundBridge.stop();
            }
            catch(Exception e)
            {
                txbridgeLogger.i18NLogger.warn_ibvp_stopfailed(XAHelper.xidToString(xid), e);
            }
        }
    }

    /**
     * Perform afterCompletion cleanup activities such as releasing resources.
     *
     * Caution: may not be invoked in crash recovery situations.
     */
    public void commit() throws WrongStateException, SystemException
    {
        txbridgeLogger.logger.trace("BridgeVolatileParticipant.commit(Xid="+xid+")");

        afterCompletion(Status.STATUS_COMMITTED);
    }

    /**
     * Perform afterCompletion cleanup activities such as releasing resources.
     *
     * Caution: may not be invoked in crash recovery situations.
     */
    public void rollback() throws WrongStateException, SystemException
    {
        txbridgeLogger.logger.trace("BridgeVolatileParticipant.rollback(Xid="+xid+")");

        afterCompletion(Status.STATUS_ROLLEDBACK);
    }

    /**
     * Invoke afterCompletion on the subordinate JTA tx.
     *
     * @param status a jakarta.transaction.Status value, normally STATUS_COMMITTED or STATUS_ROLLEDBACK
     */
    private void afterCompletion(int status)
    {
        txbridgeLogger.logger.trace("BridgeVolatileParticipant.afterCompletion(Xid="+xid+", status="+status+"/"+JTAHelper.stringForm(status)+")");

        // this is a null-op, the afterCompletion is done implicitly at the XAResource commit/rollback stage.
    }

    /**
     * Deprecated, should never be called.
     */
    public void unknown() throws SystemException
    {
        txbridgeLogger.logger.trace("BridgeVolatileParticipant.unknown(Xid="+xid+"): NOT IMPLEMENTED");
    }

    /**
     * VolatileParticipants don't support recovery, so this should never be called.
     */
    public void error() throws SystemException
    {
        txbridgeLogger.logger.trace("BridgeVolatileParticipant.unknown(Xid="+xid+"): NOT IMPLEMENTED");
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy