Search code examples
javaspring-bootspring-webfluxproject-reactorreactor

How to organise return Mono condition in controller?


Learning reactive programming now. I have simple Spring-Boot application and simple controller method, where I want to make simple condition in Get mapping:

@GetMapping(value = "/to-do/{toDoId}", produces = {
            MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE})
    public Mono<ResponseEntity<?>> getToDo(@PathVariable String toDoId) {
        return repository.findById(toDoId)
                .map(x -> new ResponseEntity<>(repository.findById(toDoId), HttpStatus.OK))
                .defaultIfEmpty(new ResponseEntity<>("To do with id" + toDoId + " does not exist", HttpStatus.NOT_FOUND));
    }

So my idea is to check if to-do exists. If yes, then I return mono response entity which includes to-do entity, if not, I return mono response entity with not found status and simple message. In tutorials I found out, that for such cases can be used defaultIfEmpty() method. I tried it, but

  .defaultIfEmpty(new ResponseEntity<>("To do with id" + toDoId + " does not exist", HttpStatus.NOT_FOUND));

Has wrong type which differs from return type:

Required type:
ResponseEntity
<Mono<ToDo>>
Provided:
ResponseEntity
<String>
no instance(s) of type variable(s) exist so that String conforms to Mono<ToDo> inference variable T has incompatible bounds: equality constraints: Mono<ToDo> lower bounds: String

What I'm doing wrong and how can this simple check be implemented?


Solution

  • It's because of the map:

    .map(x -> new ResponseEntity<>(repository.findById(toDoId), HttpStatus.OK))

    Instead of using the String value retrieved from the repository x, you are populating the body with another call to the repository (a Mono<ToDo>). Replace repository.findById(toDoId) with x and it should work.