Does ResponseEntity<Stream<MyObject>> stores everything in the memory?

Viewed 269

It seems like a simple question, but I can't find the answer.

In spring-boot, I have a Controller method which returns json:

@GetMapping
public ResponseEntity<Stream<MyObject>> get() {
  return ResponseEntity
    .ok()
    .contentType(MEDIA_JSON)
    .body(service.stream());
}

Is this properly streamed to the user (in chunks) or is the whole stream loaded into the memory before returning to the user?

1 Answers

I did not find anything in the documentation, but it is possible to try and see how it behaves.

Let's create 2 endpoints and an infinite stream of objects:

@RestController
public class MyController {

    @GetMapping("/stream")
    public ResponseEntity<Stream<MyObject>> stream() {
        return ResponseEntity.ok(getStream());
    }

    @GetMapping("/nostream")
    public ResponseEntity<List<MyObject>> noStream() {
        return ResponseEntity.ok(getStream().collect(Collectors.toList()));
    }

    private Stream<MyObject> getStream() {
        return IntStream.iterate(0, i -> i + 1)
                .mapToObj(i -> new MyObject());
    }

    static class MyObject {

        private String name = "foo";

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}

Calling http://localhost:8080/stream will respond immediately generating an infinite sequence of [{"name":"foo"},{"name":"foo"}...

If you profile the application you can see that it can proceed for minutes without increasing the memory usage:

Profiling with stream

Instead, calling the http://localhost:8080/nostream endpoint will result quickly in a java.lang.OutOfMemoryError:

Profiling without stream

Related