WebSockets in Grails 3.0
For those who aren’t familiar, WebSockets are a long-lived, interactive, two-way channel between a client browser and end server that allows ongoing communication without polling. They’ve been around for a few years now ever since being proposed by RFC 6455 and pretty much all of the major browsers have gained support since then. Spring, the ever-popular Java MVC framework, gained built-in WebSocket support in version 4.0 and that support has since been incorporated into Spring Boot and Grails (Grails support is supplied by this helpful plugin). This article is a high level overview of some tinkering I did to familiarize myself with WebSockets while also learning about the relatively-recent shakeup of Grails as it advanced to 3.0.
Specifically, my use case was to examine ways to avoid manual server polling when sending data back and forth between a server and 1-n clients. For this I decided to use WebSockets managed by SockJS, a library that handles the nitty-gritty of establishing and maintaining those connections, and Stomp, a messaging protocol built for WebSockets. Being a developer with lots of Java experience, my initial reaction to this stack was “it’s JMS, but better”. Those who have worked with Java Message Service probably know what I’m referring to – JMS allows reliable, highly-customizable cross-system messaging but can be heavy, hard to configure, and definitely doesn’t have any graceful integration into the sort of web applications being developed these days. This stack supplies many of the same capabilities while being simpler, lighter-weight, and downright simple to integrate:
- Pub/Sub Model – messages are published to customizable endpoints (think of them as mailboxes), interested clients can subscribe/unsubscribe at-will
- Topics and Queues – determine how and to whom messages get delivered: broadcast, first-come, or targeted consumer
- Delivery Acknowledgement and Transactions – bundle sets of messages to guarantee an entire batch gets worked or rolled back in case of error
- Filtering – clients can specify what types of messages they wish to receive or ignore
- Security – integrates with Spring Security and readily supports common tools like CSRF tokens
For this example I decided to setup a very simple test application. This application would generate (fake) stock quotes at a relatively high frequency, high enough that it would become burdensome to have clients poll often enough to keep up. On top of showcasing this poll-less approach I also wanted to look into the ability to allow clients to interact and decided to go for the tried-and-true chat room use case.
All the code for this example is available out on GitHub so I will just be highlighting the most important functional bits here. First up is the code that generates data for my faux stock ticker – this code runs in the background on the server pushing new quotes out to a Stomp topic that clients can subscribe to.
Next, we need some more server-side code to arbitrate chat messages – effectively, this code reflects any incoming messages out to all listeners.
Now that all the server code is in place, we create a basic webpage. The code below provides the ability for the user to subscribe and unsubscribe to stock quotes, send chat messages, and receive messages sent by other users.
Put it all together and launch as a Grails application and you get something like you see below. You can open any number of browser tabs and they will all receive the same stock quote data at the same time (provided they each subscribe) and they all can participate in a shared chat. The best part? No background AJAX requests barraging the server for the latest data.
Once you take out all the fluff, we were just able to put together a neat little app that handles some non-trivial interactions in just a few dozen lines of code. Of course, this is hardly a complex example of WebSockets or Grails but hopefully it has shown you a quick way to simplify a common use case using some neat tools. Take a look at the source out on GitHub, and happy coding!