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

com.atomikos.jms.internal.ConsumerProducerSupport Maven / Gradle / Ivy

There is a newer version: 6.0.0
Show newest version
/**
 * Copyright (C) 2000-2023 Atomikos 
 *
 * LICENSE CONDITIONS
 *
 * See http://www.atomikos.com/Main/WhichLicenseApplies for details.
 */

package com.atomikos.jms.internal;

import javax.jms.JMSException;

import com.atomikos.datasource.xa.session.InvalidSessionHandleStateException;
import com.atomikos.datasource.xa.session.SessionHandleState;
import com.atomikos.icatch.CompositeTransaction;
import com.atomikos.icatch.CompositeTransactionManager;
import com.atomikos.icatch.Synchronization;
import com.atomikos.icatch.config.Configuration;
import com.atomikos.icatch.jta.TransactionManagerImp;
import com.atomikos.logging.Logger;
import com.atomikos.logging.LoggerFactory;
import com.atomikos.recovery.TxState;

/**
 * Support for common logic in producer and consumer.
 *
 */

abstract class ConsumerProducerSupport {
    private static final Logger LOGGER = LoggerFactory.createLogger(ConsumerProducerSupport.class);

    private SessionHandleState state;

    protected ConsumerProducerSupport(SessionHandleState state) {
        this.state = state;
    }

    protected void handleException(Exception e) throws AtomikosJMSException {
        state.notifySessionErrorOccurred();
        AtomikosJMSException.throwAtomikosJMSException("Error in proxy", e);
    }

    private CompositeTransactionManager getCompositeTransactionManager() {
        CompositeTransactionManager ret = null;
        ret = Configuration.getCompositeTransactionManager();
        return ret;
    }

    protected void enlist() throws JMSException {
        CompositeTransaction ct = null;
        CompositeTransactionManager ctm = getCompositeTransactionManager();
        boolean enlist = false;

        if (ctm != null) {
            ct = ctm.getCompositeTransaction();
            if (ct != null && TransactionManagerImp.isJtaTransaction(ct)) {
                enlist = true;
            }
        }

        if (enlist) {
            registerSynchronization(ct);
            try {
                state.notifyBeforeUse(ct);
            } catch (InvalidSessionHandleStateException ex) {
                String msg = "error during enlist: " + ex.getMessage();
                LOGGER.logWarning(this + ": " + msg);
                AtomikosJMSException.throwAtomikosJMSException(msg, ex);
            }
        } else {
            String msg = "The JMS session you are using requires a JTA transaction context for the calling thread and none was found." + "\n" +
                    "Please correct your code to do one of the following: " + "\n" +            
                    "1. start a JTA transaction if you want your JMS operations to be subject to JTA commit/rollback, or" + "\n" + 
                    "2. create a non-transacted session and do session acknowledgment yourself, or" + "\n" +
                    "3. set localTransactionMode to true so connection-level commit/rollback are enabled.";
            LOGGER.logWarning(this + ": " + msg);
            AtomikosTransactionRequiredJMSException.throwAtomikosTransactionRequiredJMSException(msg);
        }

    }

    private void registerSynchronization(CompositeTransaction ct) throws AtomikosJMSException {
        if (LOGGER.isTraceEnabled()) {
            LOGGER.logTrace(this + ": detected transaction " + ct);
        }
        ct.registerSynchronization(new JmsRequeueSynchronization(ct));
    }

    private class JmsRequeueSynchronization implements Synchronization {

    	private CompositeTransaction compositeTransaction;
        private boolean afterCompletionDone;

        public JmsRequeueSynchronization(CompositeTransaction compositeTransaction) {
            this.compositeTransaction = compositeTransaction;
            this.afterCompletionDone = false;
        }

        public void afterCompletion(TxState txState) {
            if (afterCompletionDone)
                return;

            if (txState.isHeuristic() || txState == TxState.TERMINATED) {
                if (LOGGER.isTraceEnabled()) {
                    LOGGER.logTrace("JmsRequeueSynchronization: detected termination of transaction " + compositeTransaction);
                }
                state.notifyTransactionTerminated(compositeTransaction);
                if (LOGGER.isTraceEnabled()) {                    
                    LOGGER.logTrace("JmsRequeueSynchronization: is in terminated state ? " + state.isTerminated());
                }
                afterCompletionDone = true;
            }

        }

        public void beforeCompletion() {

        }

        // override equals: synchronizations for the same tx are equal
        // to avoid receiving double notifications on termination!
        public boolean equals(Object other) {
            boolean ret = false;
            if (other instanceof JmsRequeueSynchronization) {
                JmsRequeueSynchronization o = (JmsRequeueSynchronization) other;
                ret = this.compositeTransaction.isSameTransaction(o.compositeTransaction);
            }
            return ret;
        }

        public int hashCode() {
            return compositeTransaction.hashCode();
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy