Enterprise Integration Zone is brought to you in partnership with:

Adrian is a freelance consultant Java Enterprise developer with nearly 20 years experience of software development across a wide range of companies, sectors and projects. In recent years he has formed his own company and dabbled with mobile app development alongside his consultancy work. Adrian is a DZone MVB and is not an employee of DZone and has posted 9 posts at DZone. You can read more from them at their website. View Full User Profile

Spring ActiveMQ Producer Client Template

04.08.2013
| 4409 views |
  • submit to reddit

Available on GitHub

Demo available on GitHub

Overview

This is just a very small, very simple template project for sending messages to JMS queues.

In my current role we have a lot of different components and systems glued together by ActiveMQ and Camel. When developing\integration testing in this environment - it is often useful to create ad-hoc messages and send them to queues directly. This is usually the case when you need to test a subset of a larger system.

I usually knock up a test app to do this, often replicating this functionality time and time again. So I thought it might be useful to pop this into a simple template project that can be easily reused. It also made sense to 'mavenise' and 'springify' to make it more easily extensible if you need to plug in other components and features in tests.

Just to reiterate - this is just a starting point for developer style, ad hoc testing to support the development process.

Running the Demo

  1. Prerequisites
    1. Running instance of ActiveMQ (local/remote)
    2. Maven and JDK installed

  2. Configuring
    1. Edit application.properties to point to your ActiveMQ instance - specifying broker url and queue name
    2. Edit 'StartDemo.java' to provide the ObjectMessage the endpoint is expecting
    3. Type 'maven exec:java' to run the StartDemo class

application.properties
broker.url=tcp://localhost:61616
broker.queue=MyTestQueue

Looking at the Code

All the Spring configuration is set up in the main application-context.xml
application-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jms="http://www.springframework.org/schema/jms" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms.xsd
						http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

	<!-- Process Spring Annotations -->
	<context:component-scan base-package="com.cor.demo" />

	<bean id="serverProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>		
		<property name="placeholderPrefix" value="${applicationProperties."/>
		<property name="locations">
	    	<list>
	    		<value>classpath:/application.properties</value>
	    	</list>
	    </property>
		<property name="ignoreResourceNotFound" value="true"/>
	</bean>

	<!-- A JMS connection factory for ActiveMQ -->
	<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"
		p:brokerURL="${applicationProperties.broker.url}" />


	<!-- A destination in ActiveMQ -->
	<bean id="destination" class="org.apache.activemq.command.ActiveMQQueue">
		<constructor-arg value="${applicationProperties.broker.queue}" /> 
	</bean>

	<!-- A cached connection to wrap the ActiveMQ connection -->
	<bean id="cachedConnectionFactory"
		class="org.springframework.jms.connection.CachingConnectionFactory"
		p:targetConnectionFactory-ref="connectionFactory" p:sessionCacheSize="10" />

	<!-- A JmsTemplate instance that uses the cached connection and destination -->
	<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"
		p:connectionFactory-ref="cachedConnectionFactory"
		p:defaultDestination-ref="destination" />

</beans>

The ObjectMessages are created in the main StartDemo.java class
StartDemo.java
package com.cor.demo.jms;

import java.io.Serializable;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.cor.demo.jms.dispatcher.MessageDispatcher;

/**
* Just a very simple template demo that will send a single Object Message to the JMS Broker and
* Queue name defined in application.properties file. This is just for simple throwaway testing
* purposes - designed as a starting point to develop on a case by case basis.
*/
public class StartDemo {

    /**
* @param args
*/
    public static void main(String[] args) {

        // Load spring config
        ApplicationContext appContext = new ClassPathXmlApplicationContext(new String[] { "application-context.xml" });
        BeanFactory factory = (BeanFactory) appContext;

        // Send Message
        MessageDispatcher dispatcher = (MessageDispatcher) factory.getBean("messageDispatcher");
        dispatcher.sendMessageObject(getTestMessage());
    }

    /**
* Generates the test message - overwrite with your own message.
* @return The object message to be sent to the JMS Queue
*/
    private static Serializable getTestMessage() {

        return "MY TEST MESSAGE";
    }
}
Communication with the server is abstracted away into a Dispatcher object.

MessageDispatcher.java
package com.cor.demo.jms.dispatcher;

import java.io.Serializable;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.ObjectMessage;
import javax.jms.Session;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Component;

/**
 * Simple JMS Client - configured in activemq-client-context.xml.
 * @author adrian.milne
 *
 */
@Component
public class MessageDispatcher {

    /** Logger. */
    private static Logger LOG = LoggerFactory.getLogger(MessageDispatcher.class);
    
    /** JMS Template. */
    @Autowired
    protected JmsTemplate jmsTemplate;

    /**
     * Send the objectMessage to the Broker and Queue defined in application.properties.
     * @param objectMessage Object Message
     */
    public void sendMessageObject(final Serializable objectMessage) {
        
        LOG.info("Sending message " + objectMessage);
        
        jmsTemplate.send(new MessageCreator() {

            public Message createMessage(Session session) throws JMSException {
                ObjectMessage message = session.createObjectMessage(objectMessage);
                return message;
            }
        });
        
        LOG.info("Message Sent!"); 

    }

}
And that's about it really!

Conclusion 


As stated at the start - this is just a throwaway project I use as a starting point when I need to write something to send messages to an ActiveMQ Queue/

It's a compromise between something super simple (like a simple class), and something that lends itself easily to being extended. What can often start off as a simple test can grow into something more complex - and as we have maven and spring all configured at the start - it's then very easy to add in extra dependencies if you find you need them.
Published at DZone with permission of Adrian Milne, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)