Tuesday night I gave a talk at a local Java User Group (that’s four JUG appearances this year, hoorah!) on RabbitMQ and demonstrated not just using it communicate between two java processes, but also as a way of communicating asynchronously between a node.js application and a java application… I have to say it was pretty awesome and I really think it opens the doors for integrating node.js applications seemlessly into an existing java infrastructure.
The setup was actually pretty simple and I have to admit I only spent a total of two days on it. I first created the node.js application front end using Socket.IO to manage websockets on both the server and client side and Ryan Dahl’s node-amqp plugin for communicating over amqp. Here’s the relevant node.js code:
I think this is pretty straightforward, but I’ll describe what’s going on here. First, we open a connection to the amqp server, which could be configured with any additional details in accordance with the amqp spec but for now it’s just hitting localhost. Once the connection is established we declare the exchange we’ll use and then declare a queue named “queueB” and bind it to the exchange using the routing key key.b.a. This will let us receive any messages from the queue with that routing key.
With all this established, we start up the web server (I am using expressjs) and once it starts up also have socket.io listen on the same port. With the infrastructure setup, we add a listener for when a client connects and route any messages sent from the client to the exchange with the routing key “key.a.b”, which will be picked up by our java app (whose queue is bound to that key on the same exchange). We also subscribe to the queue we previously setup and messages sent out on it will be published back to the client over websocket (which in turn displays it on the page).
What makes this sweet is all of it is event driven… anything recieved on the queue is pushed to the client side and whenever the client sends something over the websocket it’s published (in this case, it’s bound to anything typed into a text box on the ui). For completeness, here’s the client side javascript:
Now here comes the java application portion (brace thyself!), which will take stock ticker symbols and return a hard coded price for that ticker (but hypothetically it could be a real value). Here’s the javaclass that acts as both a listener and a publisher, with it’s onMessage method taking the message it receives, looks up the stock ticker symbol in an ImmutableMap and publishes the price using RabbitTemplate (I’ll show the configuration for it soon):
This is all configured using Spring 3.0′s annotation based configuration:
The CommonConfiguration class is used because in the presentation I showed multiple behavior. The connectionFactory bean simply defines the ConnectionFactory with various details (these are defaults in node) and the rabbitTemplate bean represents the template that will be used to listen on queueC bound to some-exchange using the routing key “key.a.b” (which if you recall is the key used when node publishes messages on the exchange). The binding() is used to just bind the queue to the exchange.
FInally, we create a SimpleMessageListener bound to the queue (this is used in the application runner class to make our StockLookup listen on the queue) and create a bean for our StockLookup, which injects a rabbitTemplate that will be used for publishing messages back out on the exchange. Whew!
Now we have the main class that is used to startup the java app and context. This could just be a one liner that just instantiates the context, but during the presentation I wanted to expose the listener to do some live demonstrations and ended by setting the StockLookup object as a listener.
That’s all… just start up the node.js application and the java app, navigate to http://localhost:3000 and entering IBM or GOOG in the text box should make the relevant stock prices show up. A neat little thing I did in the presentation was modified the java app to publish different prices and intervals, with the client side updating in real time without me doing anything in the node.js side. Fun stuff.
The relevant code is available on github at http://github.com/jamescarr/nodejs-amqp-example for trying it out on your own, the readme gives some instructions on what you’ll need to do to set it up and run it.
This was all the result of spending just a day exploring spring-amqp (which is relatively new) and getting node and java talking… I can’t wait to delve deeper and see what other potential uses will be.