Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[jetty-users] [jetty 9.1.1] Callback to WriteListener.onWritePossible() broken after set Content-Length response header

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)

How to set Content-Length for response correctly?

Thanks

Back to the top