4

I have read this post and I don't know if it is a stupid question. I am completely newbie in reactive programming.

The question is very simple: supposing I have a fully-reactive back-end, how can I stream to browser (a large text, for instance), and print each chunk to the user as soon as they come from server?

Probably I am missing some important conceptual points, but all I need to know is: Can I send small parts of data (from server to browser), with one single HTTP GET (? or not) request? The key is: can I write those small parts, until the whole data is sent?

Thanks for any help. I really tried google before, but I always get information about other concepts (like websockets, long-polling, react.js), that I think it is not the case.

EDIT: I'am not asking for a specific API ou library. I just want to understand the concept, for example: "You CANNOT do this with HTTP protocol, period!" or "This has NOTHING to do with Reactive Programming, you are confused about what stream really means. See 'something_else.js' ".

EDIT2: I did a small rest controller using spring-mvc (spring-boot) with this method:

@RequestMapping(value = "/flush", method = RequestMethod.GET)
public void flushTest(HttpServletResponse response) {

    response.setContentType("text/html");
    response.setStatus(SC_OK);

    try (ServletOutputStream outputStream = response.getOutputStream()) {
        for (int i = 0; i < 3; i++) {
            String chunk = "chunk_" + i;
            outputStream.print(chunk);
            outputStream.flush();
            response.flushBuffer();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

}

In the browser, only the whole response arrived, even using the flushBuffer. After some research, that this could be a TOMCAT issue, I changed my pom.xml including undertow:

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-undertow</artifactId>
</dependency>

With default configurations:

server.undertow.accesslog.enabled=true
server.undertow.accesslog.dir=target/logs
server.undertow.accesslog.pattern=combined
server.compression.enabled=true
server.compression.min-response-size=1l

At this moment, using debug in my IDE, each chunk was being written after the flushBuffer.

So, I believe this could be a TOMCAT configuration. Long story short, I know there are a lot of things to help me on "streaming solutions", and thanks for all the comments, but my problem was a little bit more conceptual.

Community
  • 1
  • 1
Igor Veloso
  • 487
  • 2
  • 8
  • 20
  • Java != Javascript. Did you mean to tag RxJava or Javascript? – OneCricketeer Apr 17 '17 at 16:44
  • HTTP GET doesn't send "from server to browser". The browser sends a GET. The browser initialized a websocket. And if you have a websocket, *then* can the server send data, and it is the *front-end* that is reacting to the server. – OneCricketeer Apr 17 '17 at 16:47
  • @cricket_007, thanks for the comment. I tagged RxJS because I believe it is a example of how to solve my "problem" in the front-end side. I did not mean to say the server SEND the data. But suppose a Rest HTTP Request to GET a list of objects. In the backend I want something (that I don't know what) to a make a "flush" with some objects. And, in the front-end, I want to print those "N" object, while I wait for the others objects. – Igor Veloso Apr 17 '17 at 18:10
  • Are you simply asking about AJAX requests, then? I'm not sure RxJS is really necessary for that – OneCricketeer Apr 17 '17 at 19:21
  • I edited my post. Thanks for your comment, @cricket_007. – Igor Veloso Apr 18 '17 at 14:38

1 Answers1

8

There is a protocol on top of HTTP which allows delivery of a server response in smaller, ready-to-be-consumed, chunks to the browser using HTTP transport. It's called SSE (Server Sent Events) or EventSource, here is pretty thoroughly assembled article on the topic.

There are other means to stream data using the HTTP protocol. One such alternative is JSON streaming, in which you write partial responses on the wire from the server and consume the JSON chunks when they arrive. On the consuming side a popular library is called Oboe.js, on the server side you basically need to write the partial data on the response wire when you want to sent it, or when it's available.

For both approaches Rx is useful for handling the streaming logic on the server side. You model the pieces as a stream (handle errors, etc.) and eventually, in the Subscriber, you write the single emissions on the wire, closing the response when the Observable is finished.

On the client side, the EventSource events can be wrapped in a new Observable (via Rx.Observable.create()) and processed further as a stream. Also Oboe.js events can be converted into Observables (via Rx.Observable.fromEvent().

mkulke
  • 496
  • 3
  • 5
  • Hi Mr. @mkulke, I accepted your answer as a solution, because probably is the right way to handle this issue. But I edited my post, and the problem I had was much more simple to understand. Any thoughts, please leave a comment. – Igor Veloso Apr 18 '17 at 14:36
  • 2
    @IgorVeloso When streaming you have to pay attention to network pieces in between, like load-balancers and reverse-proxies, they often buffer the messages. Whether your server delivers data correctly in chunks you can verify by using `curl -N localhost:8080/my/endpoint` (the response should be printed in chunks). Also, on client-side, in AJAX calls the whole response is collected before handed over as response. More recent browser do support `xhr.onprogress`, which allows partial processing of responses. – mkulke Apr 18 '17 at 19:33