Search code examples
rabbitmqspring-amqpspring-rabbit

How Register multiple message listner in RabbitMQ (Spring AMQP)


I am new to rabbitmq. I am using spring-rabbit 1.3.5 Release. I want to register multiple message listner. How to do that?

I can register a single message listner.

Here is my code:

1)Interface which extends MessageListner interface

public interface MessageQueueManager extends MessageListener{
        public String createQueue(String queueName);

        public void sendMessage(String message, String destinationQueueName) throws Exception;
}

2) Here is the implementation:

 @Service("messageQueueManager")
    public class MessageQueueManagerImpl implements MessageQueueManager {

    @Autowired
        private AmqpAdmin admin;
        @Autowired
        private AmqpTemplate template;
        @Autowired
        private ConnectionFactory connectionFactory;
        @Autowired
        private SimpleMessageListenerContainer container;

        @Override
        public void onMessage(Message message) {
                // Different message can behave differently.    

        }

        @Override
        public String createQueue(String queueName) {

            // survive a server restart
            boolean durable = true;
            // keep it even if nobody is using it
            boolean autoDelete = false;
            boolean exclusive = false;
            // create queue
            Queue newQueue = new Queue(queueName, durable, exclusive, autoDelete);
            queueName = admin.declareQueue(newQueue);

            // create binding with exchange
            // Producer sends to an Exchange and a Consumer receives from a Queue, the bindings that connect Queues to Exchanges are critical for connecting those producers and consumers via messaging.
            /*admin.declareBinding(new Binding(queueName, DestinationType.QUEUE,
                    "directExchange", queueName, new HashMap<String, Object>()));*/
            Binding binding = BindingBuilder.bind(newQueue).to(DirectExchange.DEFAULT).with(queueName);
            admin.declareBinding(binding);

            // add queue to listener
            container.addQueues(newQueue);

            // start listener
            container.start();
            return queueName;
        }

        @Override
        public void sendMessage(String message, String destinationQueueName)
                throws Exception {
            template.convertAndSend("directExchange", destinationQueueName,
                    MessageBuilder.withBody(message.getBytes()).build());

        }
    }

3)Listner register in applicationContext.xml file

<!-- Listener container for setting up concurrent listeners for queues -->
    <bean id="simpleMessageListenerContainer"
        class="org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer">
        <constructor-arg index="0" ref="connectionFactory" />
        <property name="missingQueuesFatal" value="false" />
        <property name="concurrentConsumers" value="5" />
        <property name="autoStartup" value="false" />
        <property name="messageListener" ref="messageQueueManager" />
    </bean>

So here SimpleMessageListenerContainer class can take only one messageListner. Do I need to declare multiple SimpleMessageListenerContainer instance to register different messageListner?

I want to register this class as a message listner.

@Service("myMessageListener")
public class MessageHandler  implements MessageListener {
    @Override
    public void onMessage(Message message) {
        log.info("Received message: " + message);
        log.info("Text: " + new String(message.getBody()));
    }

}

Solution

  • 1)Register your queues:

    <rabbit:queue id="spring.queue" auto-delete="false"  durable="true" exclusive="false" name="spring.queue"/>
    <rabbit:queue id="user.login.notification" auto-delete="false"  durable="true" exclusive="false" name="user.login.notification"/>
    

    2)Declare the bindings:

    <rabbit:direct-exchange name="directExchange" auto-delete="false">
            <rabbit:bindings>
                <rabbit:binding queue="spring.queue" key="spring.queue" />
                <rabbit:binding queue="user.login.notification" key="user.login.notification MAIYAM" />
            </rabbit:bindings>
        </rabbit:direct-exchange>
    

    3)Tell the container to call onMessage(Message message) method when the any of the queue publishes the message.

    <rabbit:listener-container
            connection-factory="connectionFactory" acknowledge="auto" concurrency="10"
            requeue-rejected="true">
            <rabbit:listener ref="myMessageListener" queues="spring.queue" />
            <rabbit:listener ref="messageQueueManager" queues="user.login.notification" />
        </rabbit:listener-container>
    

    4)Remove private SimpleMessageListenerContainer container; from MessageQueueManagerImpl class.

    Now it should work.