1

I'm trying to stream the ouput of ProcessBuilder via the response object. Right now I get the output on my client side only after the process is completed. I would like to see the output on client side being printed at the same time. Currently this is my code and it prints out everything in the client side (POSTMAN) after the process is done.

 StreamingOutput stream = new StreamingOutput() {
        @Override
        public void write(OutputStream os) throws IOException, WebApplicationException {
            String line;
            Writer writer = new BufferedWriter(new OutputStreamWriter(os));
            BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
            try {
                while ((line = input.readLine()) != null) {
                    writer.write("TEST");
                    writer.write(line);
                    writer.flush();
                    os.flush();;
                }
            } finally {
                os.close();
                writer.close();
            }            
        }
    };
    return Response.ok(stream).build();
user1807948
  • 338
  • 6
  • 14

1 Answers1

2

What you need is to set the output buffer content length to 0, so that jersey does not buffer anything. See this for more detail: calling flush() on Jersey StreamingOutput has no effect

Here is a Dropwizard standalone application that demonstrates this:

public class ApplicationReddis extends io.dropwizard.Application<Configuration>{

    @Override
    public void initialize(Bootstrap<Configuration> bootstrap) {
        super.initialize(bootstrap);
    }

    @Override
    public void run(Configuration configuration, Environment environment) throws Exception {
        environment.jersey().property(ServerProperties.OUTBOUND_CONTENT_LENGTH_BUFFER, 0);
        environment.jersey().register(StreamResource.class);
    }

    public static void main(String[] args) throws Exception {
        new ApplicationReddis().run("server", "/home/artur/dev/repo/sandbox/src/main/resources/config/test.yaml");
    }

    @Path("test")
    public static class StreamResource{ 

        @GET
        public Response get() {
            return Response.ok(new StreamingOutput() {

                @Override
                public void write(OutputStream output) throws IOException, WebApplicationException {
                    for(int i = 0; i < 100; i++) {
                        output.write(("Hello " + i + "\n").getBytes());
                        output.flush();
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).build();
        }
    }

}

Never mind the Dropwizard part, it is simply using jersey under the hood.

environment.jersey().property(ServerProperties.OUTBOUND_CONTENT_LENGTH_BUFFER, 0);

This part sets the outbound length to 0. This will cause jersey to not buffer anything.

You will still need to flush the outputstream in the StreamingOutput as that one has its own buffer.

Running my above code with Dropwizard 1.0.2 will yield one line "hello " each 100ms. Using curl I can see that all output is printed immediately.

You should read the documentation and the side effects of setting the OUTBOUND_CONTENT_LENGTH_BUFFER to make sure you are not introducing unwanted side effects.

Community
  • 1
  • 1
pandaadb
  • 6,306
  • 2
  • 22
  • 41
  • Any idea how the client/requester can use this streamed data. Basically he will receive a stream as the response. Just want to know how to handle that situation. – prime Mar 21 '18 at 05:41
  • 1
    Same as always, there is no difference towards the client other than it will receive response data sooner. All responses, always, are streams of data. Your framework takes care of making this something you can work with (i.e. a formdata, a json body, a String etc). But there is absolutely nothing stopping your from accessing the raw data of the response stream and processing it yourself. – pandaadb Mar 21 '18 at 11:52