Wednesday, February 23, 2011

HTML5 WebSockets Adventure

I just recently spent a few days exploring the jungle that is WebSocket support in browsers and servers and I lived to tell about it. I say that it is a jungle because it is obvious to me that with the specification (IETF) not yet finalized this technology is still on the "bleeding edge".

I think it is important to note my particular frame of reference, my world view...I normally do not wish to pull the sources, build my own binary, hack on the default app server jar files, etc. My preference is to find a solution, download a binary version, install/unzip, run and load an out-of-the-box example. In addition, I am looking for a Java-based server, one I can extend with my own custom Java components - ideally a Java EE Servlet container.

My WebSockets Use Case
Thinking like the average Java web developer, I wish extend pieces of my server-side enterprise infrastructure out to the client browser application. One of the reasons that I am excited about HTML5 is that feels like client-server development of the mid-90s - back in the dark ages of PowerBuilder and Delphi. :-) Today, you primarily have to use Adobe Flash Flex for those ultra-rich, real-time capable browser-based UIs but that could change with HTML5. Note: I do not consider Silverlight nor JavaFX to be a real competitor to Flash-based applications at this time.

So, I want to build "dashboards", in jQuery, where the client-side browser is pushed data in real-time. Where my server-side Java architecture is likely a distributed fabric/grid or messaging and where particular data of interest can flow easily to my end-users just as it does around the average datacenter. OK, that might not be the average web app use case, but it is the one I am most interested in.


Step 1: Find a Browser

First thing to point out is that I am not one of the cool kids - I am still running Windows (v7 64-bit). I haven't joined the rush of hardcore techies who are sporting sexy MacBook Pros or big iron Linux workstations.
* Chrome 9.0.597.98 - supports WebSockets out of the box
* Safari 5.0.3 (7533.19.4) - supports WebSockets out of the box
* Opera 11.01 build 1190 - needs to be enabled by end-user
http://my.opera.com/ODIN/blog/2010/12/17/new-html5-features-in-opera-11
* Firefox 4.0b11 - needs to be enabled by end-user
https://developer.mozilla.org/en/WebSockets
* iOS 4.2.1 (8C148) on my iPhone 3G (wifi only supported, killed AT&T service plan)
* Android 2.2 on my Motorola DroidX - no - I also looked at Opera Mobile for the Android but that did not seem to support WebSockets

Testing browsers for WebSockets support
http://websocket.org/echo.html
http://jimbergman.net/websocket-web-browser-test/ - however, this one malfunctioned with my FireFox4

Step 2: Learn

Learn enough to be dangerous, never enough to be great. I am just getting started with a new capability and only had a couple of days to invest so far - needed to get moving as fast as possible. How does every technology explorer get moving these days? Google. Not only is Google your secret weapon for trivia night at the local pizza joint/bar, it can become your lifeline. I found many examples and several of those are now outdated, they just do not work. A few examples are provided by Aditya Yadav for the book Deploying HTML5. One using Netty and another using Jetty - I could not get either one to work - could be user error or could be they are based on the older version of the spec.

One thing that I noticed that demonstrates the relative immaturity of this space, when things do fail, you often do not receive error messages on the servers, nor in the browsers. If you are using a browser-based debugger (e.g. Firebug, Dragonfly), at least you will receive JavaScript error messages, but nothing specific to WebSockets malfunction. In the vast majority of my tests there was only silent (but deadly) failure.

Step 3: Find a Server
My "short-list" of solutions to explore included:
Kaazing
Resin
Jetty
Atmosphere (with JBoss, Spade, Tomcat and Jetty)
Infinispan

Kaazing
Obviously a commercial product with a professional grade website, cited in the html5rocks.com presentation for WebSockets and hosts a really cool online demo at Kaazing.me.

Download, installation, running example in mere moments, it just works. I did not spend more time on Kaazing because I am looking for something that is more Java EE server like.

Resin by Caucho
The Resin team provides a nice write-up on WebSockets at caucho.com/resin-4.0/examples/websocket-java/index.xtp
This particular tutorial broke down for me when I noticed that the client portion of the example was written in PHP. I just do not have the patience to translate the PHP into JSP - call me lazy.

Jetty by Webtide
While Jetty is very popular amongst Java developers who use it as a solution for localhost automated testing (JUnit, TestNG, Selenium, etc), it is not a server that I have spent a lot of time on. The Jetty world is a bit confusing on its own - there are many, many versions, from multiple download sites and multiple Eclipse plug-ins. Just google for "Jetty Download" or "Jetty Eclipse plugin" and you will see what I mean. It can take you several attempts to find the right combination to get everything working.

Then, if you google for "Jetty WebSockets" you end up with a lot of results, but no tutorial, no documented "getting started" that I could find.

Atmosphere
Atmosphere is not specifically a server, it is an open source library/framework that can be added to your favorite Java server (e.g. Tomcat, JBoss, etc). Atmosphere is where I spent the largest portion of my exploratory time - I really wanted to make this one work. It has many examples, including pub-sub with jQuery, my specific area of interest. This one certainly looked the most promising before I dove in.

Atmosphere + JBoss 6
I started with this combination because I get a paycheck from Red Hat so it tends to be my favorite Java application server. Well, that turned into a few hours of hacking away for no positive results. There was someone who wrote up his notes in the Atmosphere Users List but I was unable to follow the same path to make it work.

Atmosphere + Tomcat
I also failed to make Tomcat 6 and Atmosphere work together. Some of the setup/errors are identical to JBoss (it embeds Tomcat) like getting the right version of tc-native1.dll but I was weary after the JBoss attempt and didn't really push hard on Tomcat.

Atmosphere's Spade Server
After a few hours of frustration, I then realized that Atmosphere has an "out-of-the-box" ready to go server so I assumed THAT had to be the answer - downloaded, unzipped, started, fail! The startup looks like
java -jar atmosphere-spade-server-0.6.5.jar -a atmosphere-websocket-chat-0.6.5.war
As I said earlier in the post, you often get no error messages and this was a specific example that I remember. It even loads the page into your browser but nothing happens, clicking the buttons does not work.

At this point, I realized that I was going to need some help - Google, reviewing blog posts and digging through email list archives via Nabble was simply not getting me anywhere. So I jumped on the IRC channel and found jfarcand, the fellow who basically answers all the questions on the email list and blogs for Atmosphere. He was very kind and helpful, my basic question was...is there a setup that is just known to work? answer: Atmosphere + Jetty

Atmosphere + Jetty
Wow, it just works. After several hours of beating my head against the proverbial wall with standalone Resin, standalone Jetty and other Atmosphere combinations this was an amazingly blissful moment. I was able to get the atmosphere-websocket-chat-0.6.5.war to work immediately. And I was also able to figure out what combination of Jetty's WTP plug-in and server played nicely with each other - so I have this little demo editable inside of Eclipse Helios with drag & drop deployment to Jetty.

Infinispan
Infinispan was actually the first place I started when I begin this journey. There is a nice write-up/tutorial on using WebSockets with Infinispan and an example that ships with the distribution. Unfortunately, like almost all of my attempts, version 4.2.0.Final fails "out-of-the-box" with current browsers. The good news is that Galder Z was able to dig in immediately, figure out the specific problem and get it fixed - I have tested his patch and things look very good for 4.2.1.Final.

Conclusion
I had originally thought I could have my own custom application built using WebSockets with the weekend + two business days I had budgeted for the effort. Alas, I was only able to get some out-the-box-examples working with Atmosphere + Jetty and with Infinispan + patch. With that said, I am still very excited about the next generation of web development using the new features that fall under the HTML5 umbrella. The best part about being in the IT business is the constant change - tough to get bored - but that is obviously a double-edged sword. :-)

13 comments:

  1. maybe you will find my blog at http://www.ajeeshwrites/blogspot.comuseful for a full example?

    ReplyDelete
  2. Hey Burr, thanks for reporting the issue with the Infinispan Websocke server. It's hard to keep up with this fast moving spec but hopefully things will calm down as the spec matures.

    ReplyDelete
  3. rainman - I did run through your example, thank you very much! Here is a better URL to your blog - http://ajeeshwrites.blogspot.com/2011/02/peek-at-websockets.html

    ReplyDelete
  4. thanks for pointing that out. have updated the link to the source in github.

    ReplyDelete
  5. Do you by chance have a link to download your jetty+atmmosphere project?

    I've been banging my head against the wall for two days now on almost all the technologies you tried in this post.

    Great post btw.

    ReplyDelete
  6. raiman's blog contains a link to his solution at
    GitHub: https://github.com/ajeeshpu/html5-webapp

    Blog: http://ajeeshwrites.blogspot.com/2011/02/peek-at-websockets.html

    I didn't push my version up to GitHub because I was just following his tutorial - this can be frustrating experience :-)

    I have a new demo using HornetQ and JBoss AS6 - it works "out of the box" but I need to get somethings recorded and written down.

    ReplyDelete
  7. Thanks rainman for the html5 example , was really usefull.

    ReplyDelete
  8. A year later...
    I need to follow your footsteps to implement a WebSockets server. Would you still recommend Jetty7 + Atmosphere? Or something else?

    Thanks.

    ReplyDelete
  9. Karen & Bill, I have found that Netty is an easy solution but Jetty is still doable.

    A friend of mine, Wesley Hales, worked on an example of embedding Jetty in a .war to then run on JBoss.
    http://wesleyhales.com/blog/2012/01/20/Sending-CDI-events-to-the-browser-with-websockets/

    Netty ships inside of JBoss AS7, works with HornetQ and with Infinispan. I do not happen to have a pointer to solid docs on how to use Netty for websockets.

    ReplyDelete
  10. If you are interested in Ruby on Rails on JBoss - check out the Websockets support in TorqueBox

    http://torquebox.org/news/tags/stomp/

    My favorite use case is real-time async push to clients (desktop or mobile) using a "messaging" model.

    ReplyDelete
  11. Thank you for sharing Burr.

    I'm now using Atmosphere jQuery client and Atmosphere inside JBoss AS 7.1.1 by implementing MeteorService.

    Works very well by using Comet transport in Firefox.

    However, I haven't yet successful in using WebSockets. I've tried Kaazing and the demo works well locally.

    I tried HornetQ with Stomp WebSockets but it doesn't work, gives me 403 Forbidden. Not sure why, probably same origin policy problem or something else.

    JBoss 7.1.1 also doesn't support WebSocket, support is coming in JBoss 7.1.2 and Atmosphere 1.0 is planned to support it.

    Anyway, I'm moving on... I'm feeling good because I know that when the circumstances improve, I won't need to change anything on the client side, and hopefully minor adjustments on the server side to be able to enable WebSockets. At all times, the end-user won't be aware anyway whether it uses comet, WebSocket, or long-polling. It will just work. :-)

    ReplyDelete
    Replies
    1. Hello Hendy,
      Yes, we have made a change in AS 7.1.2 that has not yet shipped - it is likely that we will roll up this change and many others in AS 7.2.0. Errai currently takes advantage of this change to enable Websockets for its GWT-focused Bus technology. Our TorqueBox team currently uses something closer to the HornetQ with Stomp approach but plans to upgrade to the same mechanism that Errai uses.
      I have not yet had a chance to test either solution. Nor have I tried the HornetQ approach with AS7.1.x. I do plan to get back to it after JBoss World this year.

      Look for more websockets capabilities from JBoss in later 2012. Hopefully we wil get the implementation stabilized with proper docs & examples soon.

      Delete
  12. please help me..
    I have a problem in primefaces push chat..
    In script handleMessage(data) method execute 3 times when we send global message once..

    my code is same as primefaces code.
    please answer me as soon as possible....
    i can't understand why this happen...

    ReplyDelete