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

org.skyscreamer.nevado.jms.NevadoMessageConsumer Maven / Gradle / Ivy

package org.skyscreamer.nevado.jms;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.skyscreamer.nevado.jms.destination.NevadoDestination;
import org.skyscreamer.nevado.jms.destination.NevadoQueue;
import org.skyscreamer.nevado.jms.destination.NevadoTemporaryQueue;
import org.skyscreamer.nevado.jms.destination.NevadoTopic;
import org.skyscreamer.nevado.jms.message.NevadoMessage;

import javax.jms.*;
import javax.jms.IllegalStateException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

public class NevadoMessageConsumer implements MessageConsumer, QueueReceiver, TopicSubscriber {
    private final Log _log = LogFactory.getLog(getClass());

    private boolean _closed = false;
    private final NevadoSession _session;
    private final NevadoDestination _destination;
    private final String _selector;
    private final boolean _noLocal;
    private volatile MessageListener _messageListener;
    private final AtomicReference _messageParking = new AtomicReference();

    public NevadoMessageConsumer(NevadoSession session, NevadoDestination destination, String selector, boolean noLocal)
            throws JMSException
    {
        _session = session;
        if (destination instanceof NevadoTopic)
        {
            NevadoTemporaryQueue topicEndpoint = _session.getConnection().createTemporaryQueue();
            String subscriptionArn = _session.getConnection().subscribe((NevadoTopic)destination, topicEndpoint);
            _destination = new NevadoTopic((NevadoTopic)destination, topicEndpoint, subscriptionArn, false);
        }
        else
        {
            _destination = destination;
        }
        _selector = selector;
        _noLocal = noLocal;
    }

    public NevadoMessageConsumer(NevadoSession session, NevadoTopic topic, String durableSubscriptionName,
                                 String selector, boolean noLocal)
            throws JMSException
    {
        _session = session;
        NevadoQueue topicEndpoint
                = _session.createInternalQueue(_session.getDurableEndpointQueueName(durableSubscriptionName));
        String subscriptionArn = _session.getConnection().subscribe(topic, topicEndpoint);
        _destination = new NevadoTopic(topic, topicEndpoint, subscriptionArn, true);
        _selector = selector;
        _noLocal = noLocal;
    }

    public String getMessageSelector() throws JMSException {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    public MessageListener getMessageListener() {
        return _messageListener;
    }

    public void setMessageListener(MessageListener messageListener) throws JMSException {
        checkClosed();
        _messageListener = messageListener;
    }

    @Override
    public NevadoMessage receive() throws JMSException {
        return receive(-1);
    }

    @Override
    public NevadoMessage receive(long timeoutMs) throws JMSException {
        checkClosed();
        checkAsync();
        NevadoMessage message;
        try {
            message = _session.receiveMessage(_destination, timeoutMs, _noLocal);
        }
        catch(InterruptedException e) {
            Thread.currentThread().interrupt();
            return null;
        }
        tryAutoAck(message);
        return message;
    }

    @Override
    public NevadoMessage receiveNoWait() throws JMSException {
        return receive(0);
    }

    public synchronized void close() throws JMSException {
        if (!_closed)
        {
            List exceptions = new ArrayList();
            if (_destination instanceof NevadoTopic && !((NevadoTopic)_destination).isDurable())
            {
                try {
                    _session.getConnection().unsubscribe((NevadoTopic)_destination);
                } catch (JMSException e) {
                    _log.warn("Exception thrown trying to unsubscribe.  Will continue trying to close then will throw " +
                            "exception.  (First one if multiple.)", e);
                    exceptions.add(e);
                }
            }
            NevadoMessage parkedMessage;
            if ((parkedMessage = _messageParking.getAndSet(null)) != null)
            {
                _session.resetMessage(parkedMessage);
            }
            _messageListener = null;
            _closed = true;
            if (exceptions.size() > 0) {
                throw exceptions.get(0);
            }
        }
    }

    protected boolean processAsyncMessage() throws JMSException, InterruptedException {
        checkClosed();
        boolean messageProcessed = false;

        // First check for a parked message
        NevadoMessage message;
        if ((message = _messageParking.getAndSet(null)) == null)
        {
            message = _session.receiveMessage(_destination, 0, _noLocal);
        }
        if (message != null) {
            try {
                getMessageListener().onMessage(message);
                tryAutoAck(message);
                messageProcessed = true;
            }
            catch(Throwable t) {
                if (_session.getAcknowledgeMode() == Session.AUTO_ACKNOWLEDGE
                        || _session.getAcknowledgeMode() == Session.DUPS_OK_ACKNOWLEDGE)
                {
                    NevadoMessage parkedMessage;
                    if ((parkedMessage = _messageParking.getAndSet(message)) != null) {
                        _log.error("Stepped on an unexpected parked message.  Resetting it: " + parkedMessage);
                        _session.resetMessage(parkedMessage);
                    }
                }
            }
        }
        return messageProcessed;
    }

    private void tryAutoAck(NevadoMessage message) throws JMSException {
        if (message != null && _session.getAcknowledgeMode() == Session.AUTO_ACKNOWLEDGE)
        {
            message.acknowledge();
        }
    }

    private void checkAsync() throws IllegalStateException
    {
        if (_messageListener != null)
        {
            throw new IllegalStateException("Synchronous message delivery cannot be requested from a consumer after " +
                    "a message listener has been registered");
        }
    }

    public Queue getQueue() throws JMSException {
        if (_destination instanceof Queue)
        {
            return (Queue)_destination;
        }
        else
        {
            throw new IllegalStateException("getQueue() can only be called for a QueueSender");
        }
    }

    protected Destination getDestination()
    {
        return _destination;
    }

    public boolean isClosed()
    {
        return _closed;
    }

    private void checkClosed() throws IllegalStateException
    {
        if (_closed)
        {
            throw new IllegalStateException("This consumer has been closed");
        }
    }

    public Topic getTopic() throws JMSException {
        if (_destination instanceof Topic)
        {
            return (Topic)_destination;
        }
        else
        {
            throw new IllegalStateException("getTopic() can only be called for a TopicSubscriber");
        }
    }

    public boolean getNoLocal() throws JMSException {
        return _noLocal;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy