Demo: Spring + Apache Camel + Active MQ

I created this project as an illustration to my colleagues that are new to java and J2EE. The project is hosted on github.

This demo project illustrates how to use ActiveMQ in multiple-modular Spring project with shared code. One demo project is greeter-web-app or just greeter, application, that sends greeting message to the listener or listener-web-app.

The most interesting things about this code:

Messaging-related:

  • Illustration on how to send custom java bean over the JMS by using binary serialization to the StreamMessage.
  • Spring JMS module usage. See GreeterServiceImpl
  • Apache Camel usage. Consuming messages from the ActiveMQ queue and putting them to the custom bean. See ListenerRouteBuilder

Spring-related:

  • Loading properties.
  • Using mixed configuration: both annotation-driven and xml-driven configs are used in listener-web-app.
  • Spring MVC web applications.

It is fairly simple to configure JMS:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:property-placeholder location="classpath:/greeter-jms.properties"/>

    <bean id="greeterConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop">
        <property name="connectionFactory">
            <bean class="org.apache.activemq.ActiveMQConnectionFactory">
                <property name="brokerURL">
                    <value>${greeter.brokerUrl}</value>
                </property>
            </bean>
        </property>
    </bean>

    <bean id="greeterJmsOperations" class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="greeterConnectionFactory"/>
        <property name="defaultDestinationName" value="${greeter.channelName}"/>
    </bean>
</beans>

and use it then in the java code:

    @Resource(name = "greeterJmsOperations")
    private JmsOperations jmsOperations;

    @Override
    public void send(final Greeting greeting) {
        jmsOperations.send(new MessageCreator() {
            @Override
            public Message createMessage(Session session) throws JMSException {
                final StreamMessage message = session.createStreamMessage();
                message.writeString(greeting.getMessage());
                message.writeInt(greeting.getCount());
                return message;
            }
        });
    }

As for listener part I used Apache Camel, its configuration is fairly simple:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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.xsd
        http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd
        http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">

    <!--JMS broker, sample for CLUSTER URL: 'failover:(tcp://12.13.14.100:61616,tcp://12.13.14.101:61616)?randomize=true'-->
    <amq:connectionFactory id="listenerAmqConnectionFactory" brokerURL="tcp://127.0.0.1:61616"/>

    <!-- JMS channel: alexshabanov.cameldemo.greeter -->

    <bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
        <property name="connectionFactory" ref="listenerAmqConnectionFactory"/>
    </bean>

    <bean id="listenerRouteBuilder" class="com.alexshabanov.cameldemo.listener.route.ListenerRouteBuilder"/>

    <!-- Camel context -->
    <camelContext id="listenerCamelContext" xmlns="http://camel.apache.org/schema/spring">
        <routeBuilder ref="listenerRouteBuilder"/>
    </camelContext>

    <!-- Camel handlers -->
    <bean id="greetingHandler" class="com.alexshabanov.cameldemo.listener.route.handler.GreetingHandler"/>
</beans>

the most interesting parts in this config is a route builder, it’s really simple in this sample:

public final class ListenerRouteBuilder extends RouteBuilder {

    @Override
    public void configure() throws Exception {
        from("activemq:alexshabanov.cameldemo.greeter").to("greetingHandler");
    }
}

and JMS handler (greeting handler) that receives JMS stream message:

public final class GreetingHandler implements Processor {
    private final Logger log = LoggerFactory.getLogger(GreetingHandler.class);

    @Autowired
    private GreetingSinkService greetingSinkService;

    @Override
    public void process(Exchange exchange) throws Exception {
        log.info("Got exchange id={}", exchange.getExchangeId());
        final StreamMessage message = exchange.getIn().getBody(StreamMessage.class);
        final Greeting greeting = new Greeting(message.readString(), message.readInt());
        log.info("- Parsed {}", greeting);
        greetingSinkService.putGreeting(greeting);
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *