|
Making Continuations useful
Now that you've seen that Continuations allow servlet requests to be suspended without thread consumption, I need to explain a little bit more of the Continuations API to show you how to use Continuations for practical purposes.
A resume() method forms a pair with suspend(). You can think of them of as the Continuations equivalent of the standard Object wait()/notify() mechanism. That is, suspend() puts a Continuation (and therefore the execution of the current method) on hold until either its timeout expires or another thread calls resume(). The suspend()/resume() pair is key to implementing a real Comet-style service using Continuations. The basic pattern is to obtain the Continuation from the current request, call suspend(), and wait until your asynchronous event arrives. Then call resume() and generate a response.
However, unlike the true language-level continuations in languages such as Scheme, or indeed the Java language's wait()/notify() paradigm, calling resume() on a Jetty Continuation doesn't mean that code execution picks up exactly where it left off. As you've seen, what actually happens is that the request associated with the Continuation is replayed. This results in two problems: undesirable reexecution of code as in ContinuationServlet in Listing 4, and loss of state: anything in scope when the call is made to suspend() is lost.
The solution to the first of these issues is the isPending() method. If the return value of isPending() is true, this means that suspend() has been called previously, and execution of the retried request has not yet reached suspend() for the second time. In other words, making code prior to your suspend() call conditional on isPending() ensures that it executes only once per request. It's best to design your application code before the suspend() call to be idempotent, so that calling it twice won't matter anyway, but where that isn't possible you can use isPending(). Continuation also offers a simple mechanism for preserving state: the putObject(Object) and getObject() methods. Use these to hold a context object with any state you need to preserve when the Continuation is suspended. You can also use this mechanism as a way of passing event data between threads, as you'll see later on. |
|