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

com.arjuna.wst11.stub.SubordinateCoordinatorCompletionParticipantStub Maven / Gradle / Ivy

There is a newer version: 4.17.43.Final
Show newest version
package com.arjuna.wst11.stub;

import com.arjuna.wst.*;
import com.arjuna.wst.WrongStateException;
import com.arjuna.wst.SystemException;
import com.arjuna.ats.arjuna.state.OutputObjectState;
import com.arjuna.ats.arjuna.state.InputObjectState;
import com.arjuna.ats.arjuna.coordinator.ActionStatus;
import com.arjuna.mwlabs.wscf.model.sagas.arjunacore.subordinate.SubordinateBACoordinator;
import com.arjuna.wst11.*;
import com.arjuna.wst11.BAParticipantManager;
import com.arjuna.webservices11.wsba.BusinessActivityConstants;
import org.jboss.jbossts.xts.recovery.participant.ba.PersistableBAParticipant;
import org.jboss.jbossts.xts.recovery.participant.ba.XTSBARecoveryManager;

import java.io.IOException;

/**
 * A coordinator completion  participant registered on behalf of an interposed WS-BA coordinator in order
 * to ensure that durable participants in the interposed transaction are completed, closed or cancelled
 * when requested from the parent transaction.
 */
public class SubordinateCoordinatorCompletionParticipantStub
        implements BusinessAgreementWithCoordinatorCompletionParticipant, PersistableParticipant, PersistableBAParticipant
{
    public SubordinateCoordinatorCompletionParticipantStub(SubordinateBACoordinator coordinator)
    {
        this.coordinator = coordinator;
        this.coordinatorId = coordinator.get_uid().stringForm();
        this.recovered = false;
        this.manager = null;
    }

    public SubordinateCoordinatorCompletionParticipantStub()
    {
        this.coordinator = null;
        this.coordinatorId = null;
        this.recovered = true;
        this.manager = null;
    }

    /**
     * set the participant manager for this stub. this cannot be supplied to the constructor because it
     * refers to the engine which drives this participant and the engine can only be created once the
     * participant has been created. it is needed in order to be able to send a fail upward to the
     * parent coordinator during complete processing. it is not needed during close or compensate
     * processing which is ok because we cannot save and restore it anyway.
     *
     * @param manager the manager for this participant
     */
    public void setManager(BAParticipantManager manager)
    {
        this.manager = manager;
    }

    public void complete() throws WrongStateException, SystemException {
        if (!recovered) {
            // the coordinator will send complete to all participants and then
            // also run phase one commit. the former may throw an exception.
            // if the latter succeeds the tx state will be COMMITTING whereas
            // if it fails it will be ABORTED.
            try {
                coordinator.complete();
            } catch (com.arjuna.mw.wsas.exceptions.WrongStateException wse) {
                throw new WrongStateException(wse.getMessage());
            } catch (com.arjuna.mw.wsas.exceptions.SystemException se) {
                throw new SystemException(se.getMessage());
            }
            // if status is COMMITTING then we return allowing the participant to be logged
            // if status is ABORTED then the participant must fail avoiding any logging

            if (coordinator.status() == ActionStatus.ABORTED) {
                manager.fail(BusinessActivityConstants.WSBA_ELEMENT_FAIL_QNAME);
            } else {
                // null out the manager so we don't attempt to save it to the log
                manager = null;
            }
        } else {
            // we should never get asked to complete a recovered activity
            throw new WrongStateException();
        }
    }

    public void close() throws WrongStateException, SystemException {
        if (!recovered) {
            int result;
            try {
                result = coordinator.close();
            } catch (com.arjuna.mw.wsas.exceptions.SystemException se) {
                throw new SystemException(se.getMessage());
            }
            if (result != ActionStatus.COMMITTED) {
                throw new SystemException("failed to close subordinate transaction " + coordinatorId);
            }
        } else {
            XTSBARecoveryManager recoveryManager = null;
            boolean isRecoveryScanStarted = false;
            if (coordinator == null) {
                // try fetching coordinator from the recovery manager
                recoveryManager = XTSBARecoveryManager.getRecoveryManager();
                // check whether recovery has started before we check for the presence
                // of the subordinate coordinator
                isRecoveryScanStarted = recoveryManager.isSubordinateCoordinatorRecoveryStarted();
                coordinator = SubordinateBACoordinator.getRecoveredCoordinator(coordinatorId);
            }
            if (coordinator == null) {
                // hmm, still null -- see if we have finished recovery scanning
                if (!isRecoveryScanStarted) {
                    // the subtransaction may still be waiting to be resolved
                    // throw an exception causing the commit to be retried later
                    throw new SystemException();
                }
                // ok we have no transaction to commit so assume we already committed it and
                // return without error
            } else if(!coordinator.isActivated()) {
                // the transaction was logged but has not yet been recovered successfully
                // throw an exception causing the commit to be retried later
                    throw new SystemException();
            } else {
                int status = coordinator.status();

                if (status == ActionStatus.PREPARED || status == ActionStatus.COMMITTING) {
                    // ok, the commit process was not previously initiated so start it now
                    try {
                        coordinator.close();
                        SubordinateBACoordinator.removeActiveProxy(coordinatorId);
                    } catch (com.arjuna.mw.wsas.exceptions.SystemException e) {
                        // throw an exception causing the commit to be retried later
                        throw new SystemException();
                    }
                    status = coordinator.status();
                }

                // TODO -- check if this is really necessary given the catch above?
                // check that we are not still committing because of a comms timeout

                if (status == ActionStatus.COMMITTING) {
                    // throw an exception causing the commit to be retried later
                    throw new SystemException();
                }
            }
        }
    }

    public void cancel() throws FaultedException, WrongStateException, SystemException {
        if (!recovered) {
            int result = coordinator.cancel();
            if (result != ActionStatus.ABORTED) {
                throw new FaultedException("failed to compensate subordinate transaction " + coordinatorId);
            }
        } else {
            XTSBARecoveryManager recoveryManager = null;
            boolean isRecoveryScanStarted = false;
            if (coordinator == null) {
                // try fetching coordinator from the recovery manager
                recoveryManager = XTSBARecoveryManager.getRecoveryManager();
                // check whether recovery has started before we check for the presence
                // of the subordinate coordinator
                isRecoveryScanStarted = recoveryManager.isSubordinateCoordinatorRecoveryStarted();
                coordinator = SubordinateBACoordinator.getRecoveredCoordinator(coordinatorId);
            }
            if (coordinator == null) {
                // hmm, still null -- see if we have finished recovery scanning
                if (!isRecoveryScanStarted) {
                    // the subtransaction may still be waiting to be resolved
                    // throw an exception causing the commit to be retried later
                    throw new SystemException();
                }
                // ok we have no transaction to commit so assume we already committed it and
                // return without error
            } else if(!coordinator.isActivated()) {
                // the transaction was logged but has not yet been recovered successfully
                // throw an exception causing the commit to be retried later
                    throw new SystemException();
            } else {
                int status = coordinator.status();

                if (status == ActionStatus.PREPARED || status == ActionStatus.COMMITTING) {
                    // ok, the commit process was not previously initiated so start it now
                    coordinator.cancel();
                    SubordinateBACoordinator.removeActiveProxy(coordinatorId);
                }

                // check that we are not still committing because of a comms timeout

                if (status == ActionStatus.COMMITTING) {
                    // throw an exception causing the commit to be retried later
                    throw new SystemException();
                } else if (status != ActionStatus.ABORTED) {
                    throw new FaultedException();
                }
            }
        }
    }

    public void compensate() throws FaultedException, WrongStateException, SystemException {
        if (!recovered) {
            int result = coordinator.cancel();
            // test result and throw a SystemException if the compensate was delayed
        } else {
            XTSBARecoveryManager recoveryManager = null;
            boolean isRecoveryScanStarted = false;
            if (coordinator == null) {
                // try fetching coordinator from the recovery manager
                recoveryManager = XTSBARecoveryManager.getRecoveryManager();
                // check whether recovery has started before we check for the presence
                // of the subordinate coordinator
                isRecoveryScanStarted = recoveryManager.isSubordinateCoordinatorRecoveryStarted();
                coordinator = SubordinateBACoordinator.getRecoveredCoordinator(coordinatorId);
            }
            if (coordinator == null) {
                // hmm, still null -- see if we have finished recovery scanning
                if (!isRecoveryScanStarted) {
                    // the subtransaction may still be waiting to be resolved
                    // throw an exception causing the commit to be retried later
                    throw new SystemException();
                }
                // ok we have no transaction to commit so assume we already committed it and
                // return without error
            } else if(!coordinator.isActivated()) {
                // the transaction was logged but has not yet been recovered successfully
                // throw an exception causing the commit to be retried later
                    throw new SystemException();
            } else {
                int status = coordinator.status();

                if (status == ActionStatus.PREPARED || status == ActionStatus.COMMITTING) {
                    // ok, the commit process was not previously initiated so start it now
                    coordinator.cancel();
                    SubordinateBACoordinator.removeActiveProxy(coordinatorId);
                    status = coordinator.status();
                }

                // TODO -- check if this is really necessary given the catch above?
                // check that we are not still committing because of a comms timeout

                if (status == ActionStatus.COMMITTING) {
                    // throw an exception causing the commit to be retried later
                    throw new SystemException();
                } else if (status != ActionStatus.ABORTED) {
                    throw new FaultedException();
                }
            }
        }
    }

    /**
     * this should never get called
     * @throws com.arjuna.wst.SystemException
     */
    public String status() throws SystemException
    {
        return null;
    }

    /**
     * this should never get called
     * @throws com.arjuna.wst.SystemException
     */
    public void unknown() throws SystemException
    {
    }

    /**
     * this should never get called
     * @throws com.arjuna.wst.SystemException
     */
    public void error() throws SystemException
    {
    }

    /**
     * Save the state of the particpant to the specified input object stream.
     * @param oos The output output stream.
     * @return true if persisted, false otherwise.
     */
    public boolean saveState(OutputObjectState oos) {
        // we need to save the id of the subordinate coordinator so we can identify it again
        // when we are recreated
        try {
            oos.packString(coordinatorId);
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    /**
     * Restore the state of the particpant from the specified input object stream.
     * @param ios The Input object stream.
     * @return true if restored, false otherwise.
     */
    public boolean restoreState(InputObjectState ios) {
        // restore the subordinate coordinator id so we can check to ensure it has been committed
        try {
            coordinatorId = ios.unpackString();
            SubordinateBACoordinator.addActiveProxy(coordinatorId);
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    /*
     * this participant implements the PersistableBAParticipant interface so it can save its state.
     * recovery is managed by an XTS recovery module
     * @return
     * @throws Exception
     */
    public byte[] getRecoveryState() throws Exception {
        OutputObjectState oos = new OutputObjectState();
        oos.packString(this.getClass().getName());
        this.saveState(oos);
        return oos.buffer();
    }

    private SubordinateBACoordinator coordinator;
    private String coordinatorId;
    private boolean recovered;
    private BAParticipantManager manager;
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy