{{ !articles[0].partner.isSponsoringArticle ? "Platinum" : "Portal" }} Partner

CometD and Camel in the Enterprise - A Working Example

Published by

Full code is available on GitHub

All the Java code for the project is available in Github - requires Maven to run. See the README for more details - link here.

The Key Tech Players

The demo shows these various pieces of kit working (hopefully) harmoniously together:

What's the Scenario?

  • Imagine a complex enterprise infrastructure, running a bunch of different systems, servers and technologies, with data flowing between them all.
  • Commonly there will be some sort of Messaging system in play - handling routing and transformation of the various message flows. In our example we have ApacheMQ as the Messaging Server.
  • The endpoints of some of these flows may be to send data to multiple clients. One way to do this is to route messages to a Topic, and have many clients subscribed to that topic - this is easy of the clients are Java, but not so easy if the clients are Browsers.
  • Typically browser clients will have to use a hand rolled polling approach to check for new data being available.
  • Using CometD - the Browser can use some javascript to subscribe to a CometD channel, keeping a long running connection open - and the endpoint of that channel can push data down directly to all its subscribers. Handily, Apache Camel comes with a CometD plugin that can handle all this on the server side for us.

The CometD and Camel Demo

The demo shows HTML messages being sent to an ActiveMQ JMS Queue, from where they are picked up by Camel and then routed to a CometD channel endpoint.
A HTML page consumes messages from the CometD channel - and as they are received, adds them to a list on the web page. An example of the HTML page is shown below (I've added some JQuery to initially flash the images in red, and then fade them out to black over time - just to make it obvious as new messages arrive).
The messages are just simple, generated automatically from a Java client app, which pushes them to ActiveMQ using a Spring JMSTemplate.

This flow is shown in the diagram below. All three constituent parts can be run from the same project (but they must be started in the sequence shown - ActiveMQ/Camel server first, then web browser, then Java client)

Running the Demo

  • See the README file in Github for full details on how to run the demo (just remember they need to be started in the sequence above - ActiveMQ\Camel server needs to be running first for the browser to consume the cometd channel and the client to send JMS message)

The Camel Route

  • Properties are set in application.properties

  • The Camel Route - listens on a Queue and outputs to a CometD channel
		Server Camel Context (running inside ActiveMQ) 
	<camelContext xmlns="http://camel.apache.org/schema/spring">
		<!-- Load properties to Camel Context -->
		<propertyPlaceholder id="properties" location="application.properties" />
		<!-- Camel Broadcast Message Route -->
		<route id="processIncomingFilesRoute" trace="true" xmlns="http://camel.apache.org/schema/spring">

			<!-- Listen on this Queue for incoming Messages -->
			<from uri="activemq://queue:{{broker.queue}}" />

			<!-- Log to console -->
			<log message="Incoming Message - distribute via Cometd" loggingLevel="INFO" />

				Creates a Cometd channel endpoint
				Broadcast to all Cometd registered subscribers 
			<to uri="{{cometd.channel}}" />


The Javascript Consumer

google.load("jquery", "1");

 * Callback function - Cometd consumer.
google.setOnLoadCallback(function() {
    $.getScript("http://jquerycomet.googlecode.com/svn/trunk/jquery.comet.js", function(){
    console.log("done loading js");
    $.comet.subscribe("/broadcastMessageChannel", broadcastListener);

 * Listener function called on receipt of broadcast message.
function broadcastListener(msg) {
  console.log("received broadcast: " + msg + ", " + msg.data); 
  $('<li>').html(msg.data).prependTo('#contentList').animate({color: "#000000"}, 6000);
  $('html, body').animate({ scrollTop: 0 }, 0);

The Java Client Message Dispatcher

package com.cor.demo;

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;

 * Delegate for sending messages to ActiveMQ Broker via the Spring JMSTemplate.
public class MessageDispatcher {

    /** Logger. */
    private static Logger LOG = LoggerFactory.getLogger(MessageDispatcher.class);

    /** JMS Template. */
    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!");



Future Extensions

  • Obviously this is a pretty simple demo - in a real world situation you may not want to be sending raw HTML down the channel. A better solution would be JSON, allowing the client to extract and format how it wanted to.
  • (And if you're using Camel - then you're probably doing a bunch of other conversions and processing in the space between receiving and publishing the data.)


Published at DZone with permission of {{ articles[0].authors[0].realName }}, DZone MVB.

Opinions expressed by DZone contributors are their own.

{{ tag }}, {{tag}},

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}
{{ parent.authors[0].realName || parent.author}}

{{ parent.authors[0].tagline || parent.tagline }}

{{ parent.views }} ViewsClicks