package cgl.iotcloud.transport.rabbitmq;
import cgl.iotcloud.core.msg.MessageContext;
import cgl.iotcloud.core.transport.Manageable;
import cgl.iotcloud.core.transport.TransportConstants;
import com.rabbitmq.client.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
public class RabbitMQReceiver implements Manageable {
private static Logger LOG = LoggerFactory.getLogger(RabbitMQReceiver.class);
private Channel channel;
private Connection conn;
private BlockingQueue<MessageContext> inQueue;
private String queueName;
private String url;
private ExecutorService executorService;
private String exchangeName;
private String routingKey;
public RabbitMQReceiver(BlockingQueue<MessageContext> inQueue,
String queueName,
String url) {
this.inQueue = inQueue;
this.queueName = queueName;
this.url = url;
}
public void setExecutorService(ExecutorService executorService) {
this.executorService = executorService;
}
public void start() {
try {
ConnectionFactory factory = new ConnectionFactory();
factory.setAutomaticRecoveryEnabled(true);
factory.setNetworkRecoveryInterval(5000);
factory.setUri(url);
if (executorService != null) {
conn = factory.newConnection(executorService);
} else {
conn = factory.newConnection();
}
channel = conn.createChannel();
if (exchangeName != null && routingKey != null) {
channel.exchangeDeclare(exchangeName, "direct", false);
channel.queueDeclare(this.queueName, false, false, false, null);
channel.queueBind(queueName, exchangeName, routingKey);
}
boolean autoAck = false;
channel.basicConsume(queueName, false, "myConsumerTag",
new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag,
Envelope envelope,
AMQP.BasicProperties properties,
byte[] body)
throws IOException {
long deliveryTag = envelope.getDeliveryTag();
// RabbitMQMessage message = new RabbitMQMessage(properties, body);
// get the sensor id from the properties
Object sensorId = null;
Map<String, Object> props = new HashMap<String, Object>();
if (properties != null && properties.getHeaders() != null) {
sensorId = properties.getHeaders().get(TransportConstants.SENSOR_ID);
for (Map.Entry<String, Object> e : properties.getHeaders().entrySet()) {
props.put(e.getKey(), e.getValue().toString());
}
}
if (sensorId == null) {
MessageContext message = new MessageContext("default", body, props);
try {
inQueue.put(message);
} catch (InterruptedException e) {
LOG.error("Failed to put the object to the queue");
}
} else {
MessageContext message = new MessageContext(sensorId.toString(), body, props);
try {
inQueue.put(message);
} catch (InterruptedException e) {
LOG.error("Failed to put the object to the queue");
}
}
channel.basicAck(deliveryTag, false);
}
});
} catch (IOException e) {
String msg = "Error consuming the message";
LOG.error(msg, e);
throw new RuntimeException(msg, e);
} catch (Exception e) {
String msg = "Error connecting to broker";
LOG.error(msg, e);
throw new RuntimeException(msg, e);
}
}
public void stop() {
try {
channel.queueDelete(queueName, true, false);
if (channel != null) {
channel.close();
}
if (conn != null) {
conn.close();
}
} catch (IOException e) {
LOG.error("Error closing the rabbit MQ connection", e);
}
}
public void setRoutingKey(String routingKey) {
this.routingKey = routingKey;
}
public void setExchangeName(String exchangeName) {
this.exchangeName = exchangeName;
}
}