Search code examples
javaservletsbufferresponse

Servlet response buffer not flushing without newlines


My example servlet prints out some data, flushes the buffer, sleeps for 5 seconds, then prints out more data and finishes.

public void doGet(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException
{

  response.setContentType("text/html");
  PrintWriter writer = response.getWriter();
  writer.println("Before sleep<br/>");
  writer.print("After newline<br/>");
  writer.flush();
  response.flushBuffer();
  try {
    Thread.sleep(5000);
  } catch (InterruptedException e) {
  }
  writer.print("After sleep<br/>");
}

I expect the response body leading up to the flush

Before sleep<br/>
After newline<br/>

to be printed immediately, and 5 seconds later, the last piece.

Before sleep<br/>
After newline<br/>After sleep<br/>

But no

When I query this servlet with curl -v, the only immediate output is the headers and the response body leading up to (and including) the newline

Before sleep<br />

with the rest printed after 5 seconds.

Before sleep<br/>
After newline<br/>After sleep<br/>

Why?

It looks like the web container is line-buffering the response data. But that means the servlet can only flush response data before a newline, which seems to violate the specification.

Does anyone know why this is happening?

(I am using WildFly 8.2 with Java EE 7 / Servlets 3.1.)


Solution

  • After @JonSkeet suggested I look at the actual traffic, I've determined the line-buffering came from curl. The raw HTTP response from the servlet returned this immediately

    HTTP/1.1 200 OK
    Content-Type: text/html;charset=ISO-8859-1
    Transfer-Encoding: chunked
    
    26
    Before sleep<br />
    After newline<br />
    

    and after 5 seconds finished it off with

    11
    After sleep<br />
    0
    

    So maybe curl was waiting to show the After newline<br /> bit as it was reconstructing the response body from the chunked transfer encoding.

    Anyways, problem solved. Thank you!

    (edit)

    Note to self: Use this curl syntax which does not decode chunks

    curl -i --raw
    

    Now I get the output exactly as described above.