mandag 10. september 2012

HTML5 Websocket with Apache Camel

  I have made a few HTML5 Websocket examples with Apache Camel 2.10, Spring 3, Dojo Toolkit 1.7.3, and Maven. The applicaton is made runnable as a Servlet, making the demo portable.

It is very simple to make a websocket application with Apache Camel. That is actually crazy since Apache Camel is an integration framework, made for dead boring jobs of making boring computer systems communicate with each other.
Actually - Apache Camel is boring... until I discovered all the crazy possibilities with Camel.


There are many servers that is capable of websockets, but most of them offer non-portable API. The problem then is that your application becomes non portable. Not being able to move applications can have terrible effects which we see every day.

It is quite simple to create an Apache Camel application, and run it in a servlet. The Demo load the Spring ApplicationContext from web.xml, which then load the Camel Context and my application.
The websocket support is implemented as an Endpoint, which makes it quite simple to just create a simple Camel Route.

from("websocket://localhost:9292/myws")
.process(new Processor() {
 
 @Override
 public void process(Exchange exchange) throws Exception {
  exchange.getIn().setBody("Pong", String.class);    
 }
})
.to("websocket://localhost:9292/myws");

Quite simply: recieve the message, do something, send something back.

The Basic Route is a little bit more elaborate, but it is not complicated and easy to understand.

My demo on GitHub contains 3 examples.
A basic ping/pong which is a kind of a "Hello world Apache Camel Websockets".
A demo where I send tons of messages from the server, to an real-time chart in the browser
A demo that demonstrates a simple keep-alive heartbeat and re-connect functionality.

The demos are sending messages as JSON back and forth, and you can see in the Camel routes that I marshal to and from JSON, using Jackson. It's just fantastic how you can add loads of features easily with Apache Camel.

First I started to look at Atmosphere, which is a framework to give websocket support in an Servlet. I am not sure what to think of Atmosphere since I find it a bit messy where it offers several ways or styles in how you want to work with websockets.

Then Apache Camel released a new version this summer with support for Websocket. Suddenly there was an alternative. It seemed crazy since it is not a front-end framework, but I like crazy
Apache Camel is easy to learn. I bought the Camel in Action, and 6 hours later I was a pro. (I also happens to use Apache Camel in my day job). Starting to experiment with websocket support was then easy.

On client side I chose to use Dojo Toolkit since I knew it had charts and loads of other potential interesting features. I have used Dojo before, and wanted to refresh my knowledge about it. What a bad choice that would be..

Dojo is huge. 25MB and thousands of little files. Dropping this into a maven build is just stupid. Then I had to look at the overcomplicated build process, which took a lot of time to figure out, and I am not sure if the result became very good.
Then they have AMD where you code inside a function.
require([ 
 "dojo/dom",
 "dojox/socket",
 "dojo/json",
 "dojo/domReady!" // should be defined last, don't assign a return var
 ], 
 function(dom, dojoxSocket, json) {
 
 // your code in here

});
I tried to make my own module, but couldn't make it work with the custom build process. I'm sure there is something I missed, but I got bored in the end.

Dojo Websocket component(beta) is a very thin wrapper over the native api, offering fall back to long-polling(which I don't use here) and reconnect(which I couldn't make work).
var socket = dojoxSocket("ws://localhost:9292/basic");

function send(data) {
 var info = "[header:" + data.header + "|" + "content:" + data.content + "]";
 return socket.send(json.stringify(data));
}

socket.on("message", function(event) {
  var resInfo = json.parse(event.data);
 }    
});

socket.on("open", function(event) {
 var info = { "header":"msg" , "content":"hi server" };
 send(info);
});

socket.on( "error",  function(e) {
 // do something...
});

socket.on("close", function(event, args){
 socket.close();
});
The Dojo reference and api documentation is not so good since they only document the simple stuff, and does not cover all functionality. This make you waste alot of time figuring out how to use the libraries.

All in all - It was Dojo that stole most of my limited spare time, and I just had to go for "make it work" instead of "make it exquisite" which always is the goal when you want to show off stuff.

Conclusion:
Apache Camel Websocket is simple and easy to use. Client side I would rather use the native websocket api, JQuery, and a simpler chart library. Dojo is just too labour intensive if you don't have daily experience with it.

If you later should find out that the websocket implementation done by Apache Camel isn't good enough, I believe it should be simple to rip open the websocket endpoint and tweak it, since it is implemented using Jetty Websockets. Or just use Jetty Websocket directly in a portable way. Camel has shown us how that can be achieved.

I had a plan of cleaning up the js mess, and make a few examples with JMS + Websockets to illustrate how you can integrate to a system that may provide "real time" data. I'm sure you noticed the partial ActiveMQ/JMS config in the spring file

But the time is up. I figured out what I wanted, and now my interest have moved :)

The code is on GitHub - enjoy
https://github.com/frtj/camelwss

v1.1 - 10.sept.2012

Ingen kommentarer:

Legg inn en kommentar