development microservices products Spring Tanzu RabbitMQ websocket

WebSocket Architecture in Spring Framework 4.0

header-graphic-spring-STOMP-WebSocketTwo years ago, the WebSocket protocol RFC 6455 defined an important new capability for web applications: full-duplex, two-way communication between client and server. Part of the “HTML5” umbrella term, WebSocket has gathered a lot of attention and become an official buzzword—one that generates plenty of expectations, in many cases, ahead of actual experience. In this post, we will focus on separating hype from reality and introduce the Spring Framework 4.0 approach to building WebSocket-style applications using STOMP as an application-level protocol, SockJS for fallback options, and a message broker for broadcasting messages to connected users.

Considering the long list of techniques used to make the web more interactive, including Java applets, XMLHttpRequest, Adobe Flash, ActiveXObject, various Comet techniques, and server-sent events, WebSocket is an exciting, new capability. However, the truth is that WebSocket is more of a foundation. It does something very important by setting a standard for two-way communication over the web, but it’s really only the first stop. Aside from short-to-midterm challenges with network proxy configuration and browser support, WebSocket opens the door to additional architecture questions for development teams to answer.

WebSocket vs REST

To get a sense of the kinds of questions you might run into when you start thinking about a WebSocket application, have a quick look through this InfoQ post summarizing a discussion around whether WebSocket will replace REST. The degree to which the discussion seems amusing, outrageous, or plausible will vary on the type of application. Some applications have a stronger motivation for always-on, real-time interaction (e.g. games, finance, collaboration, visualization, etc) than occasional notifications (web email, news updates, etc). Either way, it’s human to relate to something familiar, and REST is how we build web applications today. So rather than resisting the idea of such a comparison, let’s go ahead and see what we can learn from it. There are two key observations to make.

First, REST is an architecture style that encourages many nouns (URLs) and a handful of verbs (HTTP methods) while remaining stateless and using hypermedia (links) among others. WebSocket by comparison points to an entirely different, messaging-style architecture. It is not merely a replacement for existing Ajax techniques and requires an event-driven, reactive approach.

Second, REST is built on HTTP, an application-level protocol on top of TCP that gives us the URLs, HTTP methods, headers, status codes, and other crucial pieces that we need to build application logic on. WebSocket, by comparison, is a thin layer over TCP. It is not much more than a stream of bytes broken down into messages with undefined content. There is very little a framework can do without making assumptions about the content within a message. When applications make such assumptions, they will have to create their own framework around those assumptions.

The WebSocket protocol does define the use of sub-protocols (aka higher-level protocols) but does not require it. Either way, an application will need to decide what message format to use—custom, framework specific, or standard.

In short, a WebSocket-style application implies an event-driven, reactive messaging architecture. Furthermore working on the WebSocket level is arguably too low level for most applications just like most web applications today aren’t programming directly to sockets.

spring-13-800x300px-final

Approaches to the Real-time Web

We can look to a number of existing frameworks with higher level messaging APIs that use WebSocket underneath and may also rely on other fallback options (e.g. HTTP streaming, long polling, etc) when necessary. Reliance on a mix of WebSocket and non-WebSocket techniques is still necessary even today. The key difference is that frameworks can provide a single API to use while transparently falling back on non-WebSocket transports if needed.

Some frameworks, like Socket.io and Vert.x, provide lightweight application facilities for responding to events and routing messages to specific handlers. Others, like CometD, provide channels for subscribing and receiving messages along with a built-in lightweight message broker. It is also an option to connect to real message brokers such as RabbitMQ or ActiveMQ directly from a browser. When it comes to messaging architectures, message brokers are suited to the role and built to scale.

The Spring Framework 4.0 Approach

One of the goals of Spring Framework 4.0—currently a release candidate, scheduled for GA in December 2013—is to provide support for WebSocket-style applications. It goes well beyond simply offering a WebSocket API on top of JSR-356 containers and also provides fallback options for use in browsers and networks that don’t support or allow use of WebSocket. More importantly, it provides a foundation for building WebSocket-style messaging architectures for use in web applications.

For fallback options we decided to use the SockJS protocol. It has the best and widest range of transports for fallback options.

For the WebSocket-style messaging architecture, we looked at many existing approaches, and we liked both the power of a real message broker as well as the feel of a web application centric programming model. After all, we need to adopt a messaging architecture, but we are also web developers used to building web application so the result shouldn’t be too different from what we know.

The first step was choosing a message format. A number of simple messaging protocols exist including STOMP, MQTT, and WAMP. These are all suitable for use in web clients and provide support for basic messaging patterns. We picked STOMP because the message format is modeled on HTTP and because it is widely supported. However, our programming model does not have a strong bias to STOMP and can be extended to support other similar protocols.

Using STOMP puts us at a level above WebSocket. It gives us a way to express who a message is for and what messages we are interested in receiving. It allows us to use available client-side libraries such as stomp.js and msgs.js, as well as plug in a real message broker for broadcasting. These are significant gains.

Spring Framework 4 provides STOMP support. With 2-3 lines of configuration, you can enable it to act as a lightweight message broker to web clients. It will automatically handle subscriptions without any server code and allow controller methods to handle incoming messages and subscriptions. This is similar to how Spring MVC maps HTTP requests to controller methods. In fact, a Spring MVC controller can be extended to also receive STOMP over WebSocket messages:

@Controller
public class GreetingController {

@RequestMapping(value=”/greeting”, method=POST)
public void httpGreet(String text) {

// ...
}

@MessageMapping("/greeting")
public void stompGreet(String text) {

// ...
}

}

Using a Full-Featured Message Broker

It is also easy to plug in a full-featured message broker. For example, RabbitMQ (or any other STOMP message broker) can be used for subscriptions for broadcasting messages to clients. In this scenario, Spring is still the web application layer that web clients connect and talk to. However, it also serves as a gateway to RabbitMQ, allowing messages from the application to flow to RabbitMQ and then back down to subscribed clients. The following diagram illustrates the approach:

Full-Featured-Message-Broker

This approach extends to multi-server and cloud environments where any number of application instances can broadcast through a RabbitMQ service and reach all connected clients regardless of which application instance they happen to be connected to. Furthermore, it’s easy to broadcast messages to connected clients from HTTP request-handling methods (i.e. REST API) or any other part of the application.

For a more detailed technical overview, see the M2 blog post on spring.io, run the Stock Portfolio sample, or watch the webinar on the Spring Dev channel. We have recently released an RC1 candidate. If you have an application in mind, now is the perfect time to try it out and provide feedback.

If you happen to be in the London area or with easy access to it, check out the Spring eXchange—a packed two-day show on Nov 14/15, with key Spring engineers presenting the latest and greatest including Spring Framework 4.0 and our STOMP over WebSocket support!