jsr340-experts@servlet-spec.java.net

[jsr340-experts] Re: Non-blocking changes

From: Shing Wai Chan <shing.wai.chan_at_oracle.com>
Date: Mon, 22 Oct 2012 16:41:02 -0700

On 10/22/12 3:11 PM, Mark Thomas wrote:
> On 22/10/2012 22:17, Shing Wai Chan wrote:
>> Based on the feedback from JavaOne, we would like to propose the
>> following changes:
>>
>> In section 5.3 of Servlet 3.1, we have
>>
>> WriteListener
>> void onWritePossible(). When a WriteListener is registered with the
>> ServletOutputStream, this method will be invoked by the container if and
>> only if canWrite method on ServletOutputStream, described below, has
>> been called and has returned false.
>>
>> In other words, one need to write as much data as possible until it is
>> blocking before the WriteListener#onWritePossible is invoked.
>> In this case, the developer need to do the following pseudo code:
>> servletOutputStream.setWriteListener(wlistener);
>> writeUntilCannotWrite(servletOutputStream); // (a) first write
>> ...
>> // (b) more write to WriteListener.onWritePossible later
>>
>> It is hard to achieve this in the application code as they need to keep
>> track of how much data has been written
>> and make it available to the WriteListener.
> Why? You write some bytes and check that "number of bytes written" ==
> "number of bytes passed to write()". I assume I am missing something.
> What is it?
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.

Shing Wai Chan


>> I propose to change the behavior that there is no need to do (a) above.
>> The WriteListener#onWritePossible will be invoked once for every write
>> operation permitted.
> I understood (or at least thought I understood) the previous proposal.
> This change is not clear to me. Please can you spell out precisely how
> you envisage that the API will work after this change.
>
>> Similarly for ReadListener.
> Ditto.
>
>> Also, we would like to rename
>> ServletOutputStream#canWrite
>> into
>> ServletOutpustStream#isReady
>> in order to be consistent with ServletInputStream
> Fine by me.
>
> Mark
>