users@servlet-spec.java.net

[servlet-spec users] [jsr340-experts] Re: Non-blocking changes

From: Rémy Maucherat <rmaucher_at_redhat.com>
Date: Tue, 23 Oct 2012 10:31:39 +0200

On 10/23/2012 01:41 AM, Shing Wai Chan wrote:
> With the proposal in EDR, we have the following:
>
> public void service(HttpServletRequest req, HttpServletResponse
> res)
> throws IOException, ServletException {
>
> ....
> output.setWriteListener(writeListener);
>
> output.write("START\n".getBytes());
> boolean prevCanWrite = true;
>
> while ((prevCanWrite = output.canWrite())) {
> writeData(output); // (a)
> }
> ...
> // then the WriteListener will be invoked later
> }
>
> static class WriteListenerImpl implements WriteListener {
> ....
>
> public void onWritePossible() {
> try {
> writeData(...); // (b)
> } catch(Exception ex) {
> throw new IllegalStateException(ex);
> } finally {
> latch.countDown();
> }
> }
> }
>
> In this case, the writeData(...) in (a) need to keep track of how much
> data has been written and then (b) will continue the writing.
To make something more realistic, I think async writing should be
combined with async, so the "main" servlet would startAsync, set the
read and write listeners, and then start doing something meaningful
either as a result of a read notification, or from another asynchronous
event which would call dispatch on the async.

The archive has the full discussion on the output algorithms, in
particular these messages described the use of canWrite in a loop and
the flag being a trigger for the listener notification (note: at the
time, there was an int "count" option to ask if "count" bytes could be
written in addition to the boolean flag; this caused some confusion, but
it was removed since):
http://java.net/projects/servlet-spec/lists/jsr340-experts/archive/2012-03/message/50
http://java.net/projects/servlet-spec/lists/jsr340-experts/archive/2012-03/message/54

The rest of the discussion thread went over all possible options, I
believe. I still don't see anything else which looks optimal while
dealing with the existing IO API.

I was fine with also adding a NIO 2 style API sendMyByteBuffer(bb,
completionHandler), since it serves an additional purpose (very similar
to Tomcat's sendfile, but more generic since data can also come from
memory rather than just the filesystem, essentially). But there wasn't
much interest, so it didn't get included.

Rémy