Search code examples
javaspring-webfluxreactive-programmingproject-reactor

What response type is better to return from reactive endpoint if we return multiple objects?


If we use reactive approach in Spring we can return Flux/Mono type in methods. So in controller it's good to wrap response ResponseEntity and return it and in case of endpoints which return one object we can write in reactive next code:

@GetMapping(value = "/to-do/{toDoId}", produces = {
            MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE})
    public Mono<ResponseEntity<ToDo>> getToDo(@Valid @PathVariable Long toDoId) {
        return repository.findById(toDoId)
                .map(ResponseEntity::ok);
    }

But what if we want to return Flux? After some experiments I found this solution:

@GetMapping(value = "/to-do", produces = {
            MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE})
    public ResponseEntity<Flux<ToDo>> getToDos() {
        return ResponseEntity.ok().body(
                repository.findAll()
        );
    }

But if I understand correct here in such format, response like ResponseEntity<Flux<ToDo>> will be blocking? So it's better to do something like <Flux<ResponseEntity<ToDo>> ? If it's so, how to get it? I should subscribe?


Solution

  • It seems you don't really use the ResponseEntity to customize the reponse status so, why not just return Mono or Flux?

    @GetMapping(value = "/to-do/{toDoId}", produces = {
                MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE})
        public Mono<ToDo> getToDo(@Valid @PathVariable Long toDoId) {
            return repository.findById(toDoId);
        }
    
    @GetMapping(value = "/to-do", produces = {
                MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE})
        public Flux<ToDo> getToDos() {
            return repository.findAll();
        }
    
    

    In any case, according to the documentation it's perfectly fine to return ResponseEntity<Mono> and ResponseEntity<Flux>, both will provide an asynchronous, non-blocking response:

    ResponseEntity<Mono> or ResponseEntity<Flux> make the response status and headers known immediately while the body is provided asynchronously at a later point. Use Mono if the body consists of 0..1 values or Flux if it can produce multiple values.