callback-websocket – creating RESTful services over a WebSocket

by poolik

Some time ago I started a side project where pushing data to users as fast as possible was a major requirement. Being easily accessible (i.e. not separataly installable) was another, so naturally, I thought this is the time to check out WebSockets.

The trouble of multiple connections

It started off great, I saw that at least two latest versions of most common (desktop) web browsers supported them, Java had a stable WebSockets API etc. But as I cracked on coding, I saw that I was using my fast full-duplex communications channel only for pushing data from the server to the client. For every client side request I still relied on the good old AJAX querying my JAX-RS endpoints.

I began wondering if there was some way to channel all of my communications through the existing WebSocket, as it seemed pointless to create additional connections to my server. As I began poking around I found this cool AngularJS WebSocket service example. The trouble was, that I had no way to intelligently handle these requests on the server.

Though replacing REST with WebSockets has been discussed before, it seems that we’re still in the early days and opinions vary. Some say that using a WebSocket eliminates many of the RESTful benefits (stateless, caching) etc, others argue that it’s speed and efficiency are more important.

I didn’t really care about whether it’s a good architectural design or not. I just wanted to eliminate waste and use my real-time requirement to my advantage. Though I couldn’t find a existing solution how to channel all of my communications over a WebSocket, I decided to create my own library – callback-websocket. It consists of a client side AngularJS WebSocket service (based on the one linked before) and a simple server side mechanism for creating request handlers.

How it works

On the client side the AngularJS WebSocketService sets a unique request id for every message going through the WebSocket and returns a promise related to that message. When receiving a message on the client side, if the message contains a request id, then the associated promise is looked up and resolved (or rejected) with the result. Resulting in a very similar API as in the standard $http service.

On the server side, every message received on the WebSocket endpoint is marshalled to the library, which then selects the correct handler for that message, based on the URL and RequestType. The response from the handler is initiated with the same request id, so it can be resolved on the client side. Handlers are dynamically found from your project source code using Classfinder. To create a handler you just have to create a class implementing the WebSocketHandler interface.

Performance

It is rather simple actually and in practice works well (for me). As mentioned earlier the main upside of using a single WebSocket is it’s speed. It has been shown previously that WebSockets can handle multiple times more messages in the same time interval. The reason for this is simple:

This graph shows that the incremental cost of processing the request/response for a REST endpoint is minimal and most of the time is spent in connection initiation/termination and honoring HTTP semantics.

– Arun Gupta

My own measurements showed similar results, where using the callback-websocket provided WebSocketService is up to ~80% faster that using the standard AngularJS $http + servlet approach.

Conclusion

The callback-websocket should be taken as what it really is – an experiment. For my small side project it works really well, the interface seems very snappy and I don’t have to deal with any framework’s complexity or HTTP protocol’s nuances, put there by features that I anyway don’t need or care about. It’s definitely not for everyone, but for those who just want something simple and fast, I think it offers a unburdened alternative.