Using Servlet 3.0 Async Features in Grails 2.0

I was talking to someone last week about the new support for Servlet 3.0 async features in Grails 2 and realized I didn’t know that much about what was available. So I thought I’d try it out and share some examples. The documentation is a little light on the subject, so first some background information.
The primary hook to do asynchronous work in the 3.0 spec is the new startAsync method in the javax.servlet.ServletRequest class. This returns an instance of the javax.servlet.AsyncContext interface which has lifecycle methods such as dispatch and complete, gives you a hook back to the request and response, and lets you register an javax.servlet.AsyncListener. You call the start method passing in a Runnable to do the asynchronous work. Using this approach frees up server resources instead of blocking, which increases scalability since you can handle more concurrent requests.
In order to use this however the servlet that handles the request must support async, and all applied filters in the filter chain must too. The main Grails servlet (GrailsDispatcherServlet) is registered in the 3.0 version of the web.xml template with the async-supported attribute set to true. And Servlet3AsyncWebXmlProcessor adds <async-supported>true</async-supported> to all filter declarations in web.xml after it’s generated. So that’s covered for you; there is no required web.xml configuration on your part.
You also have to be configured to use servlet API 3.0. This is simple to do; just change the value of grails.servlet.version to “3.0? from the default value of “2.5?. Note that there is a legacy setting in application.properties with the name app.servlet.version; you should delete this line from your application.properties file since its value is ignored and overridden at runtime by the value from BuildConfig.groovy.
You don’t call startAsync on the request from a controller though; call startAsync directly on the controller. This method is added as a controller method (wired in as part of the controllers’ AST transforms from ControllersAsyncApi (by ControllerAsyncTransformer if you’re curious)). It’s important to call the controller’s startAsync method because it does all of the standard work but also adds Grails integration. This includes adding the logic to integrate all registered PersistenceContextInterceptor instances, e.g. to bind a Hibernate Session to the thread, flush when finished, etc., and also integrates with Sitemesh. This is implemented by returning an instance of
GrailsAsyncContext which adds the extra behavior and delegates to the real instance provided by the container (e.g. org.apache.catalina.core.AsyncContextImpl in Tomcat) for the rest.
There are a few other new async-related methods available in the request; they include boolean isAsyncStarted() and AsyncContext getAsyncContext().
I’ve attached a sample application (see below for the link) to demonstrate these features. There are two parts; a simple controller that looks up stock prices asynchronously, and a chat application.
StockController is very simple. It just has a single action and suspends to look up the current stock price for the requested stock ticker. It does this asynchronously but it’s typically very fast, so you probably won’t see a real difference from the serial approach. But this pattern can be generalized to doing more time-consuming tasks.
Call http://localhost:8080/asynctest/stock/GOOG, http://localhost:8080/asynctest/stock/AAPL, http://localhost:8080/asynctest/stock/VMW, etc. to test it.
The second example is more involved and is based on the “async-request-war” example from the Java EE 6 SDK. This implements a chat application (it was previously implemented with Comet). The SDK example is one large servlet; I split it up into a controller to do the standard request work and the ChatManager class (registered as a Spring bean in resources.groovy) to handle client registration, message queueing and dispatching, and associated error handling.
The implementation uses a hidden iframe which initiates a long-running request. This never completes and is used to send messages back to each registered client. When you “login” or send a message, the controller handles the request and queues a response message. ChatManager then cycles through each registered AsyncContext and sends JSONP to the iframe which updates a text area in the main page with incoming messages.
One thing that hung me up for quite a while was that things worked fine with the SDK example but not mine. Everything looked good but messages weren’t being received by the iframe. It turns out this is due to the optimizations that are in place to make response rendering as fast as possible. Unfortunately this resulted in flush() calls on the response writer being ignored. Since we need responsive updates and aren’t rendering a large page of html, I added code to find the real response that’s wrapped by the Grails code and send directly to that.
Try it out by opening http://localhost:8080/asynctest/ in two browsers. Once you’re “logged in” to both, messages sent will be displayed in both browsers.
Some notes about the test application:
  • All of the client logic is in web-app/js/chat.js
  • grails-app/views/chat/index.gsp is the main page; it creates the text area to display messages and the hidden iframe to stay connected and listen for messages
  • This requires a servlet container that implements the 3.0 spec. The version of Tomcat provided by the tomcat plugin and used by run-app does, and all 7.x versions of Tomcat do.
  • I ran install-templates and edited web.xml to add metadata-complete="true" to keep Tomcat from scanning all jar files for annotated classes – this can cause an OOME due to a bug that’s fixed in version 7.0.26 (currently unreleased)
  • Since the chat part is based on older code it uses Prototype but it could easily use jQuery

You can download the sample application code here.

Reference: Using Servlet 3.0 Async Features in Grails 2.0 from our JCG partner Burt Beckwith at the An Army of Solipsists blog.

Related Whitepaper:

Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions

Get ready to program in a whole new way!

Functional Programming in Java will help you quickly get on top of the new, essential Java 8 language features and the functional style that will change and improve your code. This short, targeted book will help you make the paradigm shift from the old imperative way to a less error-prone, more elegant, and concise coding style that’s also a breeze to parallelize. You’ll explore the syntax and semantics of lambda expressions, method and constructor references, and functional interfaces. You’ll design and write applications better using the new standards in Java 8 and the JDK.

Get it Now!  

2 Responses to "Using Servlet 3.0 Async Features in Grails 2.0"

Leave a Reply


1 + = eight



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

15,153 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books
Get tutored by the Geeks! JCG Academy is a fact... Join Now
Hello. Add your message here.