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

com.freedomotic.bus.BusServiceImpl Maven / Gradle / Ivy

/**
 *
 * Copyright (c) 2009-2014 Freedomotic team http://freedomotic.com
 *
 * This file is part of Freedomotic
 *
 * This Program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2, or (at your option) any later version.
 *
 * This Program 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 General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * Freedomotic; see the file COPYING. If not, see
 * .
 */
package com.freedomotic.bus;

import com.freedomotic.api.EventTemplate;
import com.freedomotic.app.AppConfig;
import com.freedomotic.app.Freedomotic;
import com.freedomotic.app.Profiler;
import com.freedomotic.reactions.Command;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TemporaryQueue;
import org.apache.activemq.command.ActiveMQQueue;

/**
 * Bus services implementation.
 * 

* It is life cycle managed, see {@link LifeCycle} * * @author Freedomotic Team * */ class BusServiceImpl extends LifeCycle implements BusService { private static final Logger LOG = Logger.getLogger(BusServiceImpl.class.getName()); //private AppConfig config; private BusBroker brokerHolder; private BusConnection connectionHolder; private DestinationRegistry destination; private Session receiveSession; private Session sendSession; private Session unlistenedSession; protected MessageProducer messageProducer; @Inject public BusServiceImpl(){ //this.config = config; if (BootStatus.getCurrentStatus() == BootStatus.STOPPED) { init(); } } /** * {@inheritDoc} * * @throws java.lang.Exception */ @Override protected void start() throws Exception { BootStatus.setCurrentStatus(BootStatus.BOOTING); //config = Freedomotic.INJECTOR.getInstance(AppConfig.class); brokerHolder = new BusBroker(); brokerHolder.init(); connectionHolder = new BusConnection(); connectionHolder.init(); destination = new DestinationRegistry(this); receiveSession = createSession(); // an unlistened session unlistenedSession = createSession(); sendSession = createSession(); // null parameter creates a producer with no specified destination messageProducer = createMessageProducer(); if (sendSession == null){ throw new IllegalStateException("Messaging bus has not yet a valid send session"); } BootStatus.setCurrentStatus(BootStatus.STARTED); } private MessageProducer createMessageProducer() throws JMSException { // null parameter creates a producer with no specified destination final MessageProducer createdProducer = sendSession.createProducer(null); // configure createdProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); //final int tiemToLive = config.getIntProperty("KEY_MESSAGES_TTL", 1000); //createProducer.setTimeToLive(tiemToLive); return createdProducer; } /** * {@inheritDoc} * * @throws java.lang.Exception */ protected void stop() throws Exception { BootStatus.setCurrentStatus(BootStatus.STOPPING); messageProducer.close(); closeSession(sendSession); closeSession(unlistenedSession); closeSession(receiveSession); connectionHolder.destroy(); brokerHolder.destroy(); BootStatus.setCurrentStatus(BootStatus.STOPPED); } /** * {@inheritDoc} */ // TODO Freedomotic.java needs this method publicly visible. A whole repackage is needed. @Override public void destroy() { super.destroy(); } /** * {@inheritDoc} */ // TODO Freedomotic.java needs this method publicly visible. A whole repackage is needed. @Override public void init() { super.init(); } private void closeSession(final Session session) throws Exception { session.close(); } private Session createSession() throws Exception { return connectionHolder.createSession(); } private MessageProducer getMessageProducer() { return messageProducer; } /** * {@inheritDoc} * * @return */ @Override public BusDestination registerCommandQueue(String queueName) throws JMSException { return destination.registerCommandQueue(queueName); } /** * {@inheritDoc} * * @return */ @Override public BusDestination registerEventQueue(String queueName) throws JMSException { return destination.registerEventQueue(queueName); } /** * {@inheritDoc} * * @return */ @Override public BusDestination registerTopic(String queueName) throws JMSException { return destination.registerTopic(queueName); } /** * {@inheritDoc} * * @return */ @Override public Session getReceiveSession() { return receiveSession; } /** * {@inheritDoc} * * @return */ @Override public Session getSendSession() { return sendSession; } /** * {@inheritDoc} * * @return */ @Override public Session getUnlistenedSession() { return unlistenedSession; } private ObjectMessage createObjectMessage() throws JMSException { return getSendSession().createObjectMessage(); } /** * {@inheritDoc} */ @Override public void reply(Command command, Destination destination, String correlationID) { try { ObjectMessage msg = createObjectMessage(); msg.setObject(command); msg.setJMSCorrelationID(correlationID); msg.setStringProperty("provenance", Freedomotic.INSTANCE_ID); getMessageProducer().send(destination, msg); Profiler.incrementSentReplies(); } catch (JMSException jmse) { LOG.severe(Freedomotic.getStackTraceInfo(jmse)); } } /** * {@inheritDoc} */ @Override public Command send(final Command command) { if (command == null) { throw new IllegalArgumentException("Cannot send a null command"); } try { ObjectMessage msg = createObjectMessage(); msg.setObject(command); msg.setStringProperty("provenance", Freedomotic.INSTANCE_ID); if (command.getReceiver() == null || command.getReceiver().isEmpty()) { throw new IllegalArgumentException("Cannot send command '" + command + "', the receiver channel is not specified"); } Queue destination = new ActiveMQQueue(command.getReceiver()); if (command.getReplyTimeout() > 0) { // we have to wait an execution reply for an hardware device or // an external client final Session unlistenedSession = this.getUnlistenedSession(); TemporaryQueue temporaryQueue = unlistenedSession .createTemporaryQueue(); msg.setJMSReplyTo(temporaryQueue); // a temporary consumer on a temporary queue MessageConsumer temporaryConsumer = unlistenedSession .createConsumer(temporaryQueue); final MessageProducer messageProducer = this.getMessageProducer(); messageProducer.send(destination, msg); Profiler.incrementSentCommands(); // the receive() call is blocking LOG.config("Send and await reply to command '" + command.getName() + "' for " + command.getReplyTimeout() + "ms"); Message jmsResponse = temporaryConsumer.receive(command.getReplyTimeout()); //cleanup after receiving temporaryConsumer.close(); //TODO: commented as sometimes genenerates a "cannot publish on deleted queue" exception //check n the documentation if a temporary queue with no consumers //is automatically deleted //TODO: enable this: temporaryQueue.delete(); if (jmsResponse != null) { // TODO unchecked cast! ObjectMessage objMessage = (ObjectMessage) jmsResponse; // a command is sent, we expect a command as reply // TODO unchecked cast! Command reply = (Command) objMessage.getObject(); LOG.config("Reply to command '" + command.getName() + "' is received. Result property inside this command is " + reply.getProperty("result") + ". It is used to pass data to the next command, can be empty or even null."); Profiler.incrementReceivedReplies(); return reply; } else { LOG.config("Command '" + command.getName() + "' timed out after " + command.getReplyTimeout() + "ms"); Profiler.incrementTimeoutedReplies(); } // mark as failed command.setExecuted(false); // returns back the original inaltered command return command; } else { // send the message immediately without creating temporary // queues and consumers on it // this increments perfornances if no reply is expected final MessageProducer messageProducer = this.getMessageProducer(); LOG.log(Level.CONFIG, "Send command ''{0}'' (no reply expected)", command.getName()); messageProducer.send(destination, msg); Profiler.incrementSentCommands(); command.setExecuted(true); // always say it is executed (it's not sure but the caller is // not interested: best effort) return command; } } catch (JMSException ex) { LOG.severe(Freedomotic.getStackTraceInfo(ex)); command.setExecuted(false); return command; } } /** * {@inheritDoc} */ @Override public void send(EventTemplate ev) { send(ev, ev.getDefaultDestination()); } /** * {@inheritDoc} */ @Override public void send(final EventTemplate ev, final String to) { // TODO should this null check be here? if (ev != null) { try { ObjectMessage msg = createObjectMessage(); msg.setObject(ev); msg.setStringProperty("provenance", Freedomotic.INSTANCE_ID); // a consumer consumes on // Consumer.A_PROGRESSIVE_INTEGER_ID.VirtualTopic. BusDestination busDestination = this.registerTopic(to); Destination tmpTopic = busDestination.getDestination(); final MessageProducer messageProducer = this.getMessageProducer(); messageProducer.send(tmpTopic, msg); Profiler.incrementSentEvents(); } catch (JMSException ex) { LOG.severe(Freedomotic.getStackTraceInfo(ex)); } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy