Uploaded image for project: 'RESTEasy'
  1. RESTEasy
  2. RESTEASY-1710

StreamingOutput flush/close doesn't work in 3.1.4

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • Major
    • 4.0.0.Beta1
    • 3.1.4.Final
    • jaxrs
    • None
    • Hide

      Example failing code (works fine in 3.0.9):

      @GET
      	@Path("test")
      	@Produces("text/event-stream")
      	public StreamingOutput test(
      			@Context HttpServletRequest request,
      			@Context HttpServletResponse response) {
      		response.setStatus(HttpServletResponse.SC_OK);
      		response.setContentType("text/event-stream");
      		response.addHeader("Connection", "close");
      		try {
      			response.flushBuffer();
      		} catch (IOException e) {
      			throw new RuntimeException(e.getMessage(), e);
      		}
      
      		AsyncContext async = request.startAsync();
      		async.setTimeout(0);
      		
      		return new StreamingOutput() {
      			public void write(OutputStream outputStream)
      					throws IOException, WebApplicationException {
      				Writer writer = new BufferedWriter(new OutputStreamWriter(outputStream));
      				
      				for (int i = 0; i < 10; i++) {
      					writer.write("test " + i + "\n");
      					writer.flush();
      
      					try {
      						Thread.sleep(1000);
      					} catch (InterruptedException e) {
      						throw new RuntimeException(e.getMessage(), e);
      					}
      
      				}
      			}
      		};
      	}
      
      Show
      Example failing code (works fine in 3.0.9): @GET @Path( "test" ) @Produces( "text/event-stream" ) public StreamingOutput test( @Context HttpServletRequest request, @Context HttpServletResponse response) { response.setStatus(HttpServletResponse.SC_OK); response.setContentType( "text/event-stream" ); response.addHeader( "Connection" , "close" ); try { response.flushBuffer(); } catch (IOException e) { throw new RuntimeException(e.getMessage(), e); } AsyncContext async = request.startAsync(); async.setTimeout(0); return new StreamingOutput() { public void write(OutputStream outputStream) throws IOException, WebApplicationException { Writer writer = new BufferedWriter( new OutputStreamWriter(outputStream)); for ( int i = 0; i < 10; i++) { writer.write( "test " + i + "\n" ); writer.flush(); try { Thread .sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e.getMessage(), e); } } } }; }
    • Workaround Exists
    • Hide

      javax.servlet.ServletResponse#flushBuffer method could be used. But servletResponse instance should be passed to StreamingOutput instance in advance, and also in this case any wrapping OutputStreams won't be flushed.

      Show
      javax.servlet.ServletResponse#flushBuffer method could be used. But servletResponse instance should be passed to StreamingOutput instance in advance, and also in this case any wrapping OutputStreams won't be flushed.

    Description

      Hi, after changing resteasy dependency from 3.0.9 to 3.1.4, our StreamingOutput implementation stopped flushing data. So, the data is flushed only on exitting StreamingOutput.method.
      After investigating resteasy source code, I've found that the root cause is empty flush method in HttpServletResponseWrapper.DeferredOutputStream (code removed in https://issues.jboss.org/browse/RESTEASY-1650).

      We are using jetty 9.2.19 as a container and ServletRequest.startAsync feature to make responses async. This async invocation makes jetty not to close response (and output stream) on exit.
      Also, since jetty doesn't close the output with this async, we should take care of it ourselves, but with empty close method, it's also impossible from OutputStream

      Attachments

        Issue Links

          Activity

            People

              rhn-support-asoldano Alessio Soldano
              buggy_jira Iaroslav Shepilov (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: