org.gytheio.messaging.amqp.AmqpDirectEndpoint.java Source code

Java tutorial

Introduction

Here is the source code for org.gytheio.messaging.amqp.AmqpDirectEndpoint.java

Source

/*
 * Copyright (C) 2005-2014 Alfresco Software Limited.
 *
 * This file is part of Gytheio
 *
 * Gytheio is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Gytheio is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Gytheio. If not, see <http://www.gnu.org/licenses/>.
 */
package org.gytheio.messaging.amqp;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.qpid.amqp_1_0.jms.Connection;
import org.apache.qpid.amqp_1_0.jms.ConnectionFactory;
import org.apache.qpid.amqp_1_0.jms.Session;
import org.apache.qpid.amqp_1_0.jms.TextMessage;
import org.apache.qpid.amqp_1_0.jms.impl.ConnectionFactoryImpl;

import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Map;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageListener;

import org.gytheio.messaging.MessageConsumer;
import org.gytheio.messaging.MessageProducer;
import org.gytheio.messaging.MessagingException;
import org.gytheio.messaging.Request;

import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * A {@link MessageProducer} and message listener which interacts with AMQP
 * queues directly using Apache Qpid.
 * 
 * @author Ray Gauss II
 *
 */
public class AmqpDirectEndpoint implements MessageProducer {
    private static final Log logger = LogFactory.getLog(AmqpDirectEndpoint.class);

    private static final int DEFAULT_PORT = 5672;
    private static final String DEFAULT_USERNAME = "guest";
    private static final String DEFAULT_PASSWORD = "password";

    private static final String ENDPOINT_PREFIX_QUEUE = "queue:";
    private static final String ENDPOINT_PREFIX_TOPIC = "topic:";
    private static final String CONNECTION_PREFIX_TOPIC = "topic://";

    private String host;
    private int port = DEFAULT_PORT;
    private String username = DEFAULT_USERNAME;
    private String password = DEFAULT_PASSWORD;
    private String receiveEndpoint;
    private String sendEndpoint;

    private Connection consumerConnection;
    private Connection producerConnection;
    private Session consumerSession;
    private Session producerSession;
    private org.apache.qpid.amqp_1_0.jms.MessageProducer defaultMessageProducer;

    private MessageConsumer messageConsumer;
    private AmqpListener listener;
    private ObjectMapper objectMapper;

    protected class AmqpListener implements Runnable {
        protected boolean isInitialized = false;

        public void run() {
            try {
                Destination receiveDestination = AmqpDirectEndpoint.getDestination(getConsumerSession(),
                        receiveEndpoint);
                org.apache.qpid.amqp_1_0.jms.MessageConsumer receiver = getConsumerSession()
                        .createConsumer(receiveDestination);

                isInitialized = true;

                logger.info("Waiting for an AMQP message on " + host + ":" + receiveEndpoint);
                receiver.setMessageListener(new MessageListener() {
                    public void onMessage(final javax.jms.Message message) {
                        try {
                            logger.trace("Processing AMQP message");
                            String stringMessage = null;

                            if (message instanceof TextMessage) {
                                stringMessage = ((TextMessage) message).getText();
                            }
                            if (stringMessage != null) {
                                Object pojoMessage = objectMapper.readValue(stringMessage,
                                        messageConsumer.getConsumingMessageBodyClass());
                                if (pojoMessage == null) {
                                    logger.error("Request could not be unmarshalled");
                                } else {
                                    if (pojoMessage instanceof Request<?>) {
                                        // Check for a reply to queue message header
                                        if (StringUtils.isEmpty(((Request<?>) pojoMessage).getReplyTo())) {
                                            if (message.getJMSReplyTo() != null)

                                            {
                                                String replyQueueName = message.getJMSReplyTo().toString();
                                                if (!StringUtils.isEmpty(replyQueueName)) {
                                                    ((Request<?>) pojoMessage).setReplyTo(replyQueueName);
                                                }
                                            }
                                        }
                                    }

                                    messageConsumer.onReceive(pojoMessage);
                                }
                            } else {
                                logger.error("No valid message body found in " + message.toString());
                            }
                        } catch (JMSException | IOException e) {
                            logger.error(e.getMessage(), e);
                        }
                    }
                });

                getConsumerConnection().start();
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
        }
    }

    public void setHost(String host) {
        this.host = host;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setReceiveEndpoint(String receiveEndpoint) {
        this.receiveEndpoint = receiveEndpoint;
    }

    public void setSendEndpoint(String sendEndpoint) {
        this.sendEndpoint = sendEndpoint;
    }

    public void setMessageConsumer(MessageConsumer messageConsumer) {
        this.messageConsumer = messageConsumer;
    }

    public void setObjectMapper(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    private Connection getConsumerConnection() throws JMSException {
        if (consumerConnection == null) {
            ConnectionFactory connectionFactory = new ConnectionFactoryImpl(host, port, username, password);
            ((ConnectionFactoryImpl) connectionFactory).setTopicPrefix(CONNECTION_PREFIX_TOPIC);
            consumerConnection = connectionFactory.createConnection();

        }
        return consumerConnection;
    }

    private Connection getProducerConnection() throws JMSException {
        if (producerConnection == null) {
            ConnectionFactory connectionFactory = new ConnectionFactoryImpl(host, port, username, password);
            ((ConnectionFactoryImpl) connectionFactory).setTopicPrefix(CONNECTION_PREFIX_TOPIC);
            producerConnection = connectionFactory.createConnection();

        }
        return producerConnection;
    }

    private Session getConsumerSession() throws JMSException {
        if (consumerSession == null) {
            consumerSession = getConsumerConnection().createSession(false, Session.AUTO_ACKNOWLEDGE);
        }
        return consumerSession;
    }

    private Session getProducerSession() throws JMSException {
        if (producerSession == null) {
            producerSession = getProducerConnection().createSession(false, Session.AUTO_ACKNOWLEDGE);
        }
        return producerSession;
    }

    private static Destination getDestination(Session session, String endpoint) throws JMSException {
        Destination destination = null;
        if (endpoint.startsWith(ENDPOINT_PREFIX_QUEUE)) {
            destination = session.createQueue(endpoint.replaceFirst(ENDPOINT_PREFIX_QUEUE, ""));
        } else if (endpoint.startsWith(ENDPOINT_PREFIX_TOPIC)) {
            destination = session.createTopic(endpoint.replaceFirst(ENDPOINT_PREFIX_TOPIC, ""));
        } else {
            destination = session.createQueue(endpoint);
        }
        return destination;
    }

    private org.apache.qpid.amqp_1_0.jms.MessageProducer getDefaultMessageProducer() throws JMSException {
        if (defaultMessageProducer == null) {
            Destination sendDestination = getDestination(getProducerSession(), sendEndpoint);
            defaultMessageProducer = getProducerSession().createProducer(sendDestination);
        }
        return defaultMessageProducer;
    }

    private org.apache.qpid.amqp_1_0.jms.MessageProducer getMessageProducer(String endpoint) throws JMSException {
        if (sendEndpoint.equals(endpoint)) {
            return getDefaultMessageProducer();
        }
        Destination sendDestination = getDestination(getProducerSession(), endpoint);
        return getProducerSession().createProducer(sendDestination);
    }

    public void send(Object message) {
        send(message, sendEndpoint);
    }

    @Override
    public void send(Object message, Map<String, Object> headers) throws MessagingException {
        send(message, sendEndpoint, headers);
    }

    @Override
    public void send(Object message, String queueName, Map<String, Object> headers) throws MessagingException {
        // TODO: Would need to inspect all headers sent in to detect type and/or JMS property key
        throw new UnsupportedOperationException("Headers not currently supported");
    }

    public void send(Object message, String queueName) {
        try {
            Writer strWriter = new StringWriter();
            objectMapper.writeValue(strWriter, message);
            String stringMessage = strWriter.toString();

            if (StringUtils.isEmpty(queueName)) {
                queueName = sendEndpoint;
            }

            TextMessage textMessage = getProducerSession().createTextMessage(stringMessage);

            if (logger.isTraceEnabled()) {
                logger.trace("Sending message to " + host + ":" + queueName + ": " + stringMessage);
            }
            getMessageProducer(queueName).send(textMessage);
        } catch (Exception e) {
            throw new MessagingException("Error sending message", e);
        }
    }

    public void startListener() {
        if (listener == null) {
            listener = new AmqpListener();
        }
        listener.run();
    }

    public AmqpListener getListener() {
        if (listener == null) {
            listener = new AmqpListener();
        }
        return listener;
    }

    public boolean isInitialized() {
        return listener != null && listener.isInitialized;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder(this.getClass().getSimpleName() + "[");
        builder.append("host: " + host);
        builder.append(", ");
        builder.append("port: " + port);
        builder.append(", ");
        builder.append("username: " + username);
        builder.append(", ");
        builder.append("sendEndpoint: " + sendEndpoint);
        builder.append(", ");
        builder.append("receiveEndpoint: " + receiveEndpoint);
        builder.append(", ");
        builder.append("isInitialized: " + isInitialized());
        builder.append("]");
        return builder.toString();
    }

}