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

net.leanix.dropkit.amqp.QueueProducer Maven / Gradle / Ivy

There is a newer version: 2.0.10
Show newest version
package net.leanix.dropkit.amqp;

import com.google.inject.Inject;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ShutdownSignalException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.Map;
import java.util.UUID;

/**
 * Manages submission of messages to a RabbitMQ message queue and creation of consumers.
 * 

* Important: Try to avoid unnecessary instantiation of this class and better use a singleton pattern (eg. @Singleton). The reason * for this advice is, each new Instance of QueueProducer will affect in estabilisching a new channel to rabbitMQ but rabbitMQ * only support 65535 channels at all. *

*/ public class QueueProducer { private final Logger log = LoggerFactory.getLogger(QueueProducer.class); private final Charset utf8 = Charset.forName("UTF-8"); private final ConnectionHolder connectionHolder; private Channel channel; private final ConsumerRegistry registry; @Inject public QueueProducer(ConnectionHolder connectionHolder, ConsumerRegistry consumerRegistry) { this.connectionHolder = connectionHolder; this.registry = consumerRegistry; } public UUID submit(String jsonString, String queueName) throws IOException { byte[] msgContent = jsonString.getBytes(utf8); // ensure having a consumer for the queue (workspace) registry.consumerPresto(queueName); return performPublish(queueName, msgContent); } /** * Publish a message to a queue, creating a connection and a channel if needed. * * @param queueName * name of the queue where the message will be published * @param msgContent * content of the message */ private UUID performPublish(String queueName, byte[] msgContent) throws IOException { // Maybe too complicated -- should we instead just create a new channel here and // close it at the end of this method? // Channel creation is expensive, too. if (channel == null || !channel.isOpen()) { log.info("creating a channel to AMQP server for publishing"); channel = connectionHolder.createNewChannel(); } try { // declare (create if missing) the workspace queue as durable, // which is not removed when the connection closes (exclusive flag) // nor when there is temporarily no consumer (autodelete flag) // queue shall be automatically deleted by the server after being unused // for more than one day (unused means no consumers, no re-declares) // note that the publishing queue here needs to be declared with the same // parameters as the consuming queue in ConsumerRegistry.consumerPresto()! // and, as it is a permanent queue, with the same parameters as ever before! Map args = Collections. singletonMap("x-expires", ConsumerRegistry.QUEUE_X_EXPIRY_MILLIS); channel.queueDeclare(queueName, true, false, false, args); UUID messageId = UUID.randomUUID(); log.debug("publishing message {} to queue {}", messageId, queueName); AMQP.BasicProperties.Builder bldr = new AMQP.BasicProperties.Builder(); bldr.messageId(messageId.toString()); // FIXME encoding and content type should be set outside this method to be more flexible bldr.contentEncoding(utf8.name()); bldr.contentType("application/json"); // Make the message persistent if server goes down bldr.deliveryMode(2); // The unnamed exchange puts the message to the queue with the name // given by parameter routingKey. // We just created the queue above, so don't go into the hassle // of using the mandatory mechanism and its callback. channel.basicPublish("", queueName, false, bldr.build(), msgContent); return messageId; } catch (ShutdownSignalException e) { log.info("{} was shut down unexpectedly", e.isHardError() ? "Connection" : "Channel"); channel = null; if (e.isHardError()) { connectionHolder.closeConnection(); } } return null; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy