org.opendds.esb.actions.routing.JmsRouter.java Source code

Java tutorial

Introduction

Here is the source code for org.opendds.esb.actions.routing.JmsRouter.java

Source

/*
 *
 *
 * Distributed under the OpenDDS License.
 * See: http://www.opendds.org/license.html
 */

package org.opendds.esb.actions.routing;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import javax.naming.InitialContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.soa.esb.ConfigurationException;
import org.jboss.soa.esb.actions.ActionLifecycleException;
import org.jboss.soa.esb.actions.routing.AbstractRouter;
import org.jboss.soa.esb.helpers.ConfigTree;
import org.jboss.soa.esb.message.Message;
import org.jboss.soa.esb.util.Util;

import org.opendds.esb.helpers.ConfigTreeHelper;
import org.opendds.esb.helpers.ThreadedQueue;

/**
 * JMS Message Router implementation which focuses on simple, yet
 * efficient processing.  Each sending thread maintains a single set
 * of resources for the lifetime of the router instance.  This ensures
 * resource thrashing does not occur as in other implementations.
 * <p/>
 * A number of features remain to be implemented:
 * <li>
 *  <ul>ESB Message unwrapping (i.e. unwrap)</ul>
 *  <ul>Advanced endpoints (i.e. jndi-context-factory, busidref)</ul>
 *  <ul>JMS QoS policies (i.e. persistent, priority, time-to-live)</ul>
 * </li>
 *
 * @author  Steven Stallion
 */
public class JmsRouter extends AbstractRouter {
    private static Log log = LogFactory.getLog(JmsRouter.class);

    private Connection connection;
    private Destination destination;

    private ThreadedQueue<Message> messages;

    private class MessageListener implements ThreadedQueue.QueueListener<Message> {
        private class MessageContext {
            private Session session;
            private MessageProducer producer;

            public MessageContext(Session session, MessageProducer producer) {
                this.session = session;
                this.producer = producer;
            }

            public Session getSession() {
                return session;
            }

            public MessageProducer getMessageProducer() {
                return producer;
            }
        }

        private ThreadLocal<MessageContext> contextLocal = new ThreadLocal<MessageContext>() {
            @Override
            protected MessageContext initialValue() {
                try {
                    Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
                    return new MessageContext(session, session.createProducer(destination));

                } catch (JMSException e) {
                    throw new IllegalStateException(e);
                }
            }
        };

        public void dequeue(Message message) {
            try {
                MessageContext context = contextLocal.get();

                Session session = context.getSession();
                MessageProducer producer = context.getMessageProducer();

                ObjectMessage objMessage = session.createObjectMessage();
                objMessage.setObject(Util.serialize(message));

                producer.send(objMessage);

            } catch (Exception e) {
                log.warn("Unexpected problem routing message: " + e.getMessage(), e);
            }
        }
    }

    public JmsRouter(ConfigTree config) throws ConfigurationException {
        super(config);
        try {
            InitialContext ctx = new InitialContext();

            ConnectionFactory cf = (ConnectionFactory) ctx
                    .lookup(ConfigTreeHelper.requireAttribute(config, "connection-factory"));

            connection = cf.createConnection();

            destination = (Destination) ctx.lookup(ConfigTreeHelper.requireAttribute(config, "dest-name"));

            messages = new ThreadedQueue<Message>(new MessageListener(),
                    ConfigTreeHelper.getAttribute(config, "maxThreads"));

        } catch (Exception e) {
            throw new ConfigurationException(e);
        }
    }

    @Override
    public void initialise() throws ActionLifecycleException {
        log.info("Starting OpenDDS JMS Router");
        if (log.isDebugEnabled()) {
            log.debug("Initializing " + messages.numberOfThreads() + " sending thread(s)");
        }

        super.initialise();
        messages.start();
    }

    public void route(Object o) {
        if (!(o instanceof Message)) {
            throw new IllegalArgumentException();
        }
        messages.enqueue((Message) o);
    }

    @Override
    public void destroy() throws ActionLifecycleException {
        log.info("Stopping OpenDDS JMS Router");

        messages.shutdown();
        if (!messages.isEmpty()) {
            log.warn(messages.size() + " message(s) unsent; consider increasing maxThreads!");
        }

        if (connection != null) {
            try {
                connection.close();

            } catch (JMSException e) {
            }
        }
        super.destroy();
    }
}