package cgl.iotcloud.core.transport.jms; import cgl.iotcloud.core.msg.MessageContext; import cgl.iotcloud.core.transport.Manageable; import cgl.iotcloud.core.transport.TransportConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.jms.*; import java.util.Map; import java.util.concurrent.BlockingQueue; public class JMSSender implements Manageable { private static Logger LOG = LoggerFactory.getLogger(JMSSender.class); private Connection connection; private Session session; private Destination dest; private BlockingQueue<MessageContext> outQueue; private MessageProducer producer; private ConnectionFactory conFactory; boolean topic; String destination; public JMSSender(ConnectionFactory conFactory, String destination, boolean topic, BlockingQueue<MessageContext> outQueue) { if (conFactory == null || destination == null || outQueue == null) { throw new IllegalArgumentException("All the parameters are mandatory"); } this.conFactory = conFactory; this.topic = topic; this.outQueue = outQueue; this.destination = destination; } public void start(){ try { this.connection = conFactory.createConnection(); this.connection.start(); this.session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); if (topic) { dest = session.createTopic(destination); } else { dest = session.createQueue(destination); } producer = session.createProducer(dest); // start the thread to listen Thread t = new Thread(new Worker()); t.start(); } catch (JMSException e) { String msg = "Failed to create a message producer for destination: " + destination; LOG.error(msg); throw new RuntimeException(msg, e); } } public void stop() { try { producer.close(); session.close(); connection.close(); } catch (JMSException e) { LOG.error("Error occurred while closing JMS connections"); } } private class Worker implements Runnable { @Override public void run() { boolean run = true; int errorCount = 0; while (run) { try { try { MessageContext input = outQueue.take(); // create a bytemessae BytesMessage bytesMessage = session.createBytesMessage(); bytesMessage.setStringProperty(TransportConstants.SENSOR_ID, input.getSensorId()); setMessageProperties(bytesMessage, input.getProperties()); bytesMessage.writeBytes(input.getBody()); producer.send(dest, bytesMessage); } catch (InterruptedException e) { LOG.error("Exception occurred in the worker listening for consumer changes", e); } } catch (Throwable t) { errorCount++; if (errorCount <= 3) { LOG.error("Error occurred " + errorCount + " times.. trying to continue the worker"); } else { LOG.error("Error occurred " + errorCount + " times.. terminating the worker"); run = false; } } } String message = "Unexpected notification type"; LOG.error(message); throw new RuntimeException(message); } } private static void setMessageProperties (Message msg, Map<String, Object> properties) throws JMSException { if (properties == null) { return; } for (Map.Entry<String, Object> entry : properties.entrySet()) { String propertyName = entry.getKey (); Object value = entry.getValue (); msg.setObjectProperty(propertyName, value); } } }