SitePen Support
Orbited

Implementing a Bayeux to JMS Bridge

by Jordi Albornoz-MulliganJuly 9th, 2008

At the Open Anzo project, we’re using Cometd Bayeux to expose JMS, the Java Message Service, to the browser. The Open Anzo system is built around an asynchronous message-passing architecture. I’ll describe how we expose that functionality to browser clients with a Bayeux to JMS bridge built using dojox.cometd and Jetty’s Cometd implementation. JMS is interesting because its a widely supported mechanism of accessing message brokers. So bridging between Bayeux and JMS means easily tapping into such systems.

Why Comet

The Open Anzo project uses Comet to provide a unique programming model for data stored on a server. With Open Anzo, you can replicate chunks of data from a server to work with the data locally. Those replicas are automatically kept up-to-date via Comet messages sent whenever the data changes. This model lets the developer focus on working with the data rather than focusing on the requests and mechanisms for retrieving the data. Since Open Anzo implements this model using a message broker, we are able to extend the model to the web by building a Bayeux to JMS bridge.

Nuts & Bolts

With a thin JavaScript object wrapper around Cometd and a small server side component, we are able to expose most of the basic JMS functionality to the browser. While we don’t expose every nuance of the JMS API, we can communicate with a JMS cloud as a full participant even from a browser. For our implementation we use ActiveMQ as the message broker, which has its own Comet bridge. We chose to build our own bridge using Cometd Bayeux for its various advantages such as pluggable Comet transports and resiliency across transient network failures. Also, we need it to work with any other JMS message broker.

The core of the bridge implementation is the BayeuxJMSBridge server-side component. Its sits on a Jetty server instance and listens for Bayeux messages from clients and forwards the messages via JMS on behalf of the client. It also receives messages from the JMS cloud and then forwards them onto the interested clients as a Bayeux message. Browser clients use the JMSClient object to subscribe to JMS topics or to send messages to queues. For example:

// Subscribe to a JMS topic
anzo.messaging.JMSClient.subscribeToTopics("interestingTopic",
function(msg) {
    // msg.properties contains the JMS message properties
    // msg.body contains the JMS message body
    // ...
});
 
// Send a request and expect a response.
anzo.messaging.JMSClient.publish({ properties: {}, body: "my request"},
"myDestination", function(msg) {
    // Work with response message...
}}}

Notice that the ‘publish’ method supports request/response style interactions. Internally, the JMSClient object will add a randomly generated “correlation id” to the message and save the given callback function mapped to that id. Then, whenever a message arrives on a Bayeux channel on the client, we check if it contains a correlation id. If so, we look up the corresponding callback and invoke it with the newly arrived response message. This is all transparent to the client. It simply knows that it has sent a message and its callback is eventually called with the appropriate response message. The difference between a PubSub message and a request/response message is simply that a request/response message contains a correlation id.

Whenever a browser client connects to the bridge, a new JMS temporary topic is created on behalf of that client. That is where messages bound only for that specific user will be sent. Each such topic is mapped to a Bayeux channel for the specific user (ex. “/anzo/user/myUser/34xWtez-i”). To make sure that only the intended client can subscribe to that client-specific Bayeux channel we plug in an implementation of ‘dojox.cometd.SecurityPolicy’.

Future Enhancements

For private request/response messages we create a Bayeux channel per user. We might consider a less resource intensive approach as Greg Wilkins describes. Also, JMS message brokers provide various quality of service guarantees but, with our implementation, those guarantees aren’t preserved between the browser and the bridge. We will explore some of the many methods to add service guarantees to Comet.

Conclusion

With Comet, Open Anzo is able to provide a powerful model for manipulating data on the web. Having small local replicas of data automatically kept up-to-date lets developers focus on rendering and using the data rather than building APIs to get at it. And by tapping into JMS-based infrastructure we make the browser a full participant in an asynchronous message passing architecture.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]
SitePen, Inc. Comet Services

Leave a Reply



Copyright 2014 Comet Daily, LLC. All Rights Reserved