Since Subbu wrote BigPipe using node.js, I had to see how the same thing would look like in a Java async servlet.
Stephan Schmidt had already written Facebook BigPipe for Java, but using a synchronous servlet model, not asynchronous. I decided to implement it using Jetty continuations and the Jetty HTTP client, but the code should be easy to adapt to servlet 3.0 AsyncContext
.
The code initially constructs the page with a few empty div
s that will contain the pagelets, for example:
I keep the connection open from the browser to the server while I render pagelets. As pagelets become available, I flush them onto the browser, which in turn inserts them into the right place in the DOM using Javascript. Assuming we get back a response from the remote module protocol:
We wrap it inside Javascript so that it looks like:
All is left is for the arrived
function to update the
pagelet3
element in the DOM. In terms of concurrency, the
initial page construction is done synchronously. As soon as I have the
frame in place with the div
s that will eventually hold
the pagelets, I suspend the execution of the servlet, which in turn
releases the thread that was attached to the client connection. At
that point, I fire in parallel HTTP client requests to the remote
module server.
For resuming the continuation, I could have used a counter, but since
each HTTP client execution is a separate thread, unlike in node.js, I
did not want to have to acquire a lock and synchronize to be able to
update the counter. Instead, I used request attributes, as setting,
getting and removing them is thread safe. The code keeps a list of
references to the elements that we are offloading to a remote module
server, as an ArrayList
with the ids to fire parallel
requests to http://localhost:8080/module?id={id}
; each
id
is also kept as a request attribute. As each request
comes back from the remote module server, I write and flush the
response buffer, so that the element appears on the browser
immediately, and I remove the corresponding request attribute.
Although the code is not as readable and straight forward as what Subbu got with node.js, I am actually surprised how simple the async Java solution actually turned out to be.
blog comments powered by Disqus