[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
Re: [jetty-users] [jetty 9.1.1] Callback to WriteListener.onWritePossible() broken after set Content-Length response header
|
Hi,
On Sat, Feb 8, 2014 at 10:53 AM, Zen Zhong <zenzhong8383@xxxxxxxxx> wrote:
> Hi,
>
> I'm running jetty 9.1.1, the last invocation of
> ServletOutputStream.isReady() will return true in
> WriteListener.onWritePossible(), but after I set Content-Length response
> header, then it doesn't work.
>
> test code (2 classes):
> @WebServlet(name = "EchoAsyncServlet", urlPatterns = { "/echo_async" },
> asyncSupported = true)
> public class EchoAsyncServlet extends HttpServlet {
>
> private static final long serialVersionUID = -8434727468202612595L;
>
> private static final byte[] RESPONSE = "V".getBytes();
>
> @Override
> public void service(final HttpServletRequest req, final
> HttpServletResponse resp) throws IOException {
> AsyncContext asyncCtx = req.startAsync(req, resp);
> asyncCtx.setTimeout(10_000);
> ServletOutputStream out = resp.getOutputStream();
> out.setWriteListener(new TextWriteListener(RESPONSE, asyncCtx,
> out));
> }
>
> }
>
> public class TextWriteListener implements WriteListener {
>
> private final byte[] text;
> private final AsyncContext asyncCtx;
> private final ServletOutputStream out;
>
> public TextWriteListener(byte[] text, AsyncContext asyncCtx,
> ServletOutputStream out) {
> super();
> this.text = text;
> this.asyncCtx = asyncCtx;
> this.out = out;
> }
>
> @Override
> public void onError(Throwable t) {
> t.printStackTrace();
> asyncCtx.complete();
> }
>
> private boolean written;
>
> @Override
> public synchronized void onWritePossible() throws IOException {
> while (true) {
> final boolean ready = out.isReady();
> System.out.println(String.format("onWritePossible> asyncCtx=%s,
> ready=%s, written=%s", asyncCtx, ready,
> written));
> if (!ready) {
> break;
> }
> if (written) {
> asyncCtx.complete();
> return;
> } else {
> // comment this line to test
> ((HttpServletResponse)
> asyncCtx.getResponse()).setHeader("Content-Length",
> String.valueOf(text.length));
> out.write(text);
> written = true;
> }
> }
> }
>
> }
>
> output:
> onWritePossible>
> asyncCtx=org.eclipse.jetty.server.AsyncContextState@64e0bfc9, ready=true,
> written=false
> onWritePossible>
> asyncCtx=org.eclipse.jetty.server.AsyncContextState@64e0bfc9, ready=false,
> written=true
> org.eclipse.jetty.io.EofException: Closed
> at
> org.eclipse.jetty.server.HttpOutput$AsyncICB.completed(HttpOutput.java:725)
> at
> org.eclipse.jetty.util.IteratingCallback.processIterations(IteratingCallback.java:200)
> at
> org.eclipse.jetty.util.IteratingCallback.iterate(IteratingCallback.java:126)
> at org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:270)
> at java.io.OutputStream.write(OutputStream.java:75)
> at TextWriteListener.onWritePossible(TextWriteListener.java:43)
> at org.eclipse.jetty.server.HttpOutput.run(HttpOutput.java:690)
> at
> org.eclipse.jetty.server.handler.ContextHandler.handle(ContextHandler.java:1159)
> at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:335)
> at
> org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:232)
> at
> org.eclipse.jetty.io.AbstractConnection$1.run(AbstractConnection.java:505)
> at
> org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:607)
> at
> org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:536)
> at java.lang.Thread.run(Thread.java:722)
I tried your example converting it to a test, therefore not using
annotations for the servlet, and works for me in the latest master
branch.
Your output is strange: it reports that 2 "onWritePossible>" calls are
invoked, the last with ready=false, but from the stack trace it looks
like the condition if (!ready) break is not executed and it goes on to
write more ?
Are you sure the code and the stack trace match ?
Other than that your code looks good.
--
Simone Bordet
----
http://cometd.org
http://webtide.com
http://intalio.com
Developer advice, training, services and support
from the Jetty & CometD experts.
Intalio, the modern way to build business applications.