Monday, July 16, 2012

Dynamic messaging with Qpid and Spring Integration

One of the key functions of a message broker that I would like to be able to do is to dynamically send messages to queues at runtime. This means that I don’t want to have to create queues ahead of time within the broker and then alter my application’s configuration to connect to the new queue.  What I want to do is have the application determine when it needs to create a new queue (either by customer interaction, database values, or some of arbitrary logic), and then have new messages sent to it.

With RabbitMQ, if you send a message to a queue that doesn’t exist, it creates the queue for you and then adds the message to it. Qpid, on the other hand, doesn’t work like this.  If you try to send a message to a non-existent queue, you’ll get an error.

While fishing through Qpid documentation I read that if a consumer is created for a queue that doesn’t exist, then the broker will create the queue.  This is better than nothing, but still not really what I want.

Then while testing a few different settings, I realized that from within Java, you can specify arguments (similar to the arguments you would use if you were to create a queue from the command line) when you specify the message destination.  This changes everything.  Now I can create durable queues on the fly, which is just what I wanted.

Qpid isn’t directly supported by Spring Integration in the same way that RabbitMQ is, but since it can be accessed using JMS, you can use the existing JMS classes within SI do to send and receive messages.This can be done by creating a service activator that has a DynamicJmsTemplate which will send the messages.  




The JmsTemplate will need a connection factory.  The Qpid examples use a JNDI connection factory, but I would rather have my connection defined in my config and not have to worry about JNDI.  For this, I used the AMQConnectionFactory provided in the qpid client library.  I’m not sure if this is the best class to use, but for now it will work.


 



 
  
   
  
 

At this point all you will need to do is to implement a sendMessage method within the handler class and use the JmsTemplate to send the message.  But wait, how do we guarantee that the queue will be created if it doesn’t exist when we send the message?  The trick here is specify the create arguments with the destination.

String destinationName = queueName + "; {create: always, node:{type:queue,durable:True}}";
this.jmsTemplate.convertAndSend(destinationName, objectToSend);


And there you have it. You can now create queues on the fly without having to worry about errors.  Just make sure you create a consumer for the queue you just created, otherwise your queues will fill up pretty quick.

1 comment:

  1. What type of software development suits your project? It's not always easy to find out. Here's what you need to know about custom software development

    ReplyDelete