Last updated on November 5th, 2012 (Spring MVC 3.2 RC1)
In previous blog posts I introduced the Servlet 3 based async capability in Spring MVC 3.2 and used the spring-mvc-showcase and the Spring AMQP stocks sample to demonstrate it. This post presents a chat sample where the external events are not AMQP messages but rather HTTP POST requests with chat messages. In the second part of the post, I'll switch to a distributed chat where the events are Redis notifications.
Chat is not a common requirement for web applications. However it is a good example of a requirement that can only be met with real-time notifications. It is more sensitive to time delays than email or status alerts and it is not that uncommon to chat in a browser with a friend, or with a colleague during a webinar, or with a live person on a shopping site. You can imagine other types of online collaboration.
The Sample
The spring-mvc-chat sample is available on Github. Although not the focus of this blog post, the client side uses Thymeleaf, knockout.js, and jQuery. Thymeleaf is an excellent alternative to JSPs that enables clean HTML templates with support for previews allowing a designer to double-click an HTML template and view it unlike a JSP that requires a Servlet container. knockout.js
is a client-side MVC framework that's very handy for attaching behavior to HTML elements. To get an idea about it quickly, follow one of its excellent tutorials. jQuery is used for DOM scripting and Ajax requests.
ChatController
The ChatController exposes operations to get and post chat message. Here is the method to get messages:
@RequestMapping(method=RequestMethod.GET)
@ResponseBody
public DeferredResult<List<String>> getMessages(@RequestParam int messageIndex) {
final DeferredResult<List<String>> deferredResult = new DeferredResult<List<String>>(null, Collections.emptyList());
this.chatRequests.put(deferredResult, messageIndex);
deferredResult.onCompletion(new Runnable() {
@Override
public void run() {
chatRequests.remove(deferredResult);
}
});
List<String> messages = this.chatRepository.getMessages…