Thursday, July 15, 2010

Running embedded JMS with Spring

I was experimenting on how to run active mq embedded with spring so as to ease out unit testing of queues. First i looked at the doc provided in active mq but the thing is the namespace URI provided in the site was invalid and as such it didnt work right out of the box. Then i stumbled upon this article which showed the correct namespace to include. And also you need to include xbean-spring-3.4.jar. Here is a sample i have done;

First we create the message sender;


import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;

public class JMSSender {

private JmsTemplate jmsTemplate;

private Destination destination;

public void sendMessage(final String message) {
jmsTemplate.send(destination, new MessageCreator() {

@Override
public Message createMessage(Session arg0) throws JMSException {

TextMessage msg = arg0.createTextMessage();
msg.setText(message);
return msg;
}
});
}

/**
* @return the jmsTemplate
*/
public JmsTemplate getJmsTemplate() {
return jmsTemplate;
}

/**
* @param jmsTemplate the jmsTemplate to set
*/
public void setJmsTemplate(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}

/**
* @return the destination
*/
public Destination getDestination() {
return destination;
}

/**
* @param destination the destination to set
*/
public void setDestination(Destination destination) {
this.destination = destination;
}
}


This will just send the message to the specified destination. The destination will be specified in the spring configuration which we will look at in just a little moment.

Next i write my JUnit test class to test the embedded messaging queue.


import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.TextMessage;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:test-common-context.xml")
public class JMSTest {

@Autowired
private JMSSender jmsSender;

@Autowired
@Qualifier("consumer")
private JmsTemplate jmsTemplate;

@Autowired
private Destination destination;

@Test
public void testJMSSender() {
jmsSender.sendMessage("test");
TextMessage msg = (TextMessage) jmsTemplate.receive(destination);
System.out.println("***********************");
try {
System.out.println(msg.getText());
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("***********************");
}
}


I have specified the configuration file with the annotation. In that i just import the active mq configuration file which im going to show you now.


<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:amq="http://activemq.apache.org/schema/core"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core-5.2.0.xsd">


<!-- lets create an embedded ActiveMQ Broker -->
<amq:broker useJmx="false" persistent="false">
<amq:transportConnectors>
<amq:transportConnector uri="tcp://localhost:0" />
</amq:transportConnectors>
</amq:broker>

<!-- ActiveMQ destinations to use -->
<amq:queue id="destination"
physicalName="org.apache.activemq.spring.Test.spring.embedded" />


<!--
JMS ConnectionFactory to use, configuring the embedded broker using
XML
-->
<amq:connectionFactory id="jmsFactory" brokerURL="vm://localhost" />


<!-- Spring JMS Template -->
<bean id="myJmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<qualifier value="producer" />
<property name="connectionFactory">
<!-- lets wrap in a pool to avoid creating a connection per send -->
<bean class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory">
<ref local="jmsFactory" />
</property>
</bean>
</property>
</bean>

<bean id="consumerJmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<qualifier value="consumer" />
<property name="connectionFactory" ref="jmsFactory" />
</bean>

<!-- a sample POJO which uses a Spring JmsTemplate -->
<bean id="producer"
class="JMSSender">
<property name="jmsTemplate">
<ref bean="myJmsTemplate"></ref>
</property>

<property name="destination">
<ref bean="destination" />
</property>
<!--

<property name="messageCount"> <value>10</value> </property>
-->
</bean>



</beans>





That is all you need. And now you can just run the jUnit test and you can see the result. Ofcourse there are better ways of hooking up the jms template, but the purpose of this article was not to exemplify that. If you do have any queries do let me know.


Cheers

No comments:

Post a Comment