Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [jetty-users] Question about behavior of WriteListener

Thanks for the clarification. I know that the write does not happen immediately but has expected that it at least happens for the bytes handed over to write. In the "real-world" this complete can be issued by the thread writing as well as by a timeout listener so it seems I have to merge both so the timeout knows that
a) writing has started and
b) then waits until writing is done

I'm just curious what happens on the wire: Will the container terminate the (maybe persitent) connection if it detects that content-length != bytes written?


Am 19.10.2016 16:46, schrieb Simone Bordet:
Hi,

On Wed, Oct 19, 2016 at 12:12 PM, Christoph Läubrich
<laeubi@xxxxxxxxxxxxxx>  wrote:
I have a question about the usage/behavior of WriteListener because I
encountered a strange problem: Writing works most of the time, but as soon
as the data hit some magic size-limit it is truncated.

I created a very simplified class like this:

public class ByteArrayWriteListener implements WriteListener {

   private ServletOutputStream stream;
   private byte[] data;
   private AsyncContext asyncContext;

   public ByteArrayWriteListener(byte[] data, AsyncContext asyncContext,
ServletOutputStream stream) {
     this.data = data;
     this.asyncContext = asyncContext;
     this.stream = stream;
   }

   @Override
   public void onError(Throwable t) {
   }

   @Override
   public void onWritePossible() throws IOException {
    stream.write(data);
    asyncContext.complete();
Uh, no.

   }

}

all data is written as a big bunch and then the AsyncContext is immediately
completed (note that it doesn't matter if complete is called outside the
write-listener).
That's wrong.

This leads to the effect that the client simply gets only
partial of the data when it grows up to a magic limit (maybe some response
buffer size or so seem to depend on client load also...), setting the
content-length prior to writing data has no effect. If I modify* the code
that it checks (after the write) that the stream is ready then everything
works.
Yep.

Question: is it expected that a prior write is not completed if asyncContext
is completed?
The semantic of write(), in case of async I/O, has changed so that it
does not guarantee that a write happens at all.
It could write 0 bytes, 1, N, or all of them.

Calling AsyncContext.complete() tells the container that you are done
writing, but you are actually not done until the write is actually
completed.

I can't find in the Javadoc any hint that AsyncContext.complete() might stop
any already issued writes, and would expect that it throws an exception like
calling stream.flush() for example if not isReady was called before.

Thanks in advance for any clarification :-)

* Modified code:
   @Override
   public void onWritePossible() throws IOException {
     if (!dataWritten) {
       stream.write(data);
       dataWritten = true;
Small nit on the variable naming:
Here it may not be true that the data is *written*.
It is true that you have a write *pending*.
It *may* be completed, but you can only know by calling isReady().

     }
     if (stream.isReady()) {
       asyncContext.complete();
     }
   }
So yes, this code works because the write is not done twice thanks to
the flag, and AsyncContext.complete() is called when the write is
actually finished.




Back to the top