Wednesday, October 8, 2008

ActiveMQ Message Consumer in Spring

In the last blog we saw how to configure an ActiveMQ broker to run in a Spring environment. In this blog we will see how to configure a message consumer. Again, I am not trying to explain how consumers work but just sharing code and config to make it work in Spring :p

Since we have the luxury of Spring , we will use a message listener container provided by the framework: SimpleMessageListenerContainer (org.springframework.jms.listener.SimpleMessageListenerContainer ). My needs were simple and non-transactional so this container suffices

The basic reason is the desire to be message driven i.e. I want my app to take some actions as and when it receives messages. The container bean definition should look like:

    <bean id="jmsContainer" class="org.springframework.jms.listener.SimpleMessageListenerContainer">
        <property name="autoStartup" value="true"/>
        <property name="connectionFactory" ref="myConnectionFactory"/>
        <property name="destination" ref="myDestination"/>
        <property name="messageListener" ref="myMessageListener"/>
        <property name="acceptMessagesWhileStopping" value="true"/>
    </bean>

This config makes the container start when the bean gets loaded and makes sure no messages are lost even if it is down. Further we need to specify the connection factory to use to connect to broker, the destination at broker from which we wish to hear and the message listener that ultimately handles the message. The config for these three will look like:

 <bean id="myDestination" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg value="myPackage.myQueue"/>
    </bean>

 <bean id="myConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://localhost:61636"/>
   </bean>

<bean id="myMessageListener" class="myPackage.MyMessageListener">       
    <property name="appName" value="My Application"/>
</bean>


Destination takes the name for destination in order to identify it at broker. the producer would refer it by the same name. JNDI can be used for more sophisticated look-ups which we may see some other time. Connection factory just needs url for a running broker. Message Listener is just our custom bean to handle messages. MyMessageListener would look like:

package myPackage;

import javax.jms.*;

public class MyMessageListener implements MessageListener {
    private String appName;

    public void setAppName(String appName){
        this.appName = appName;    
    }

    public void onMessage(Message message) {
        //do your stuff
    }
}

Finally, don't forget the POM dependencies included in last blog if you are using Maven. You should be good to go.

2 comments:

Unknown said...

Hi !

I am new to AMQ+SPRING and struggling to get it working.

I have scenario as below:
1. Successfully setup AMQ 5.3 server running on tcp
Defined Queue and Topics in activemq.xml, AMQ admin shows them correctly

2. In my swing client application,
on some action, class1 creates message and puts in Queue in AMQ so that only single listeners gets message.
on some action, class2 creates message and puts in Topic in AMQ so that multiple listeners get same message.

3. In swing client application, I have created spring-config.xml and posted at http://pastebin.org/617311

I am not sure if I have bind multiple consumers to Topic rightly.
Also noticed that AMQ admin shows myTopic1 and myTopic2 under "Queues" after running my app !
Your kind guidence will get me going.

Thank you very much.
Nitin

Saveen said...

Hey Nitin, I have just moved out of IT and will be pursuing higher education from October, 2010. Being in middle of zillion transitions and on the move, I am really sorry that I will not be able to help you actively. The three blog articles under ActivMQ label is all I can offer right now.