title: WebFlux: why do I need to use flatMap in CRUD
body: <p>I found examples on the Internet but this doesn't give me a full understanding. <strong>Standard CRUD when using WebFlux.</strong></p>
  
  <p><strong>Router:</strong></p>
  
  <pre><code>@Configuration
  public class PersonRouter {
  
      @Bean
      public RouterFunction&lt;ServerResponse&gt; route(PersonHandler handler) {
          return RouterFunctions
                  .route(GET("/getAllPersons").and(accept(MediaType.APPLICATION_JSON)), handler::findAll)
                  .andRoute(GET("/getPerson/{id}").and(accept(MediaType.APPLICATION_STREAM_JSON)), handler::findById)
                  .andRoute(POST("/createPerson").and(accept(MediaType.APPLICATION_JSON)), handler::save)
                  .andRoute(DELETE("/deletePerson/{id}").and(accept(MediaType.APPLICATION_JSON)), handler::delete);
      }
  
  }
  </code></pre>
  
  <p><strong>Handler:</strong></p>
  
  <pre><code>@Component
  public class PersonHandler {
  
      private final PersonService personService;
  
      public PersonHandler(PersonService personService) {
          this.personService = personService;
      }
  
      public Mono&lt;ServerResponse&gt; findById(ServerRequest request) {
          String id = request.pathVariable("id");
          return ok()
                  .contentType(MediaType.APPLICATION_JSON)
                  .body(personService.getById(id), Person.class);
      }
  
      public Mono&lt;ServerResponse&gt; findAll(ServerRequest request) {
          return ok()
                  .contentType(MediaType.APPLICATION_JSON)
                  .body(personService.getAll(), Person.class);
      }
  
      public Mono&lt;ServerResponse&gt; save(ServerRequest request) {
          final Mono&lt;Person&gt; person = request.bodyToMono(Person.class);
          return ok()
                  .contentType(MediaType.APPLICATION_JSON)
                  .body(fromPublisher(person.flatMap(personService::save), Person.class));
      }
  
      public Mono&lt;ServerResponse&gt; delete(ServerRequest request) {
          String id = request.pathVariable("id");
          return ok()
                  .contentType(MediaType.APPLICATION_JSON)
                  .body(personService.delete(id), Void.class);
      }
  
  }
  </code></pre>
  
  <p><strong>Repository:</strong></p>
  
  <pre><code>@Repository
  public interface PersonRepository extends ReactiveMongoRepository&lt;Person, String&gt; {
  }
  </code></pre>
  
  <p><strong>Service:</strong></p>
  
  <pre><code>@Service
  @Transactional
  @AllArgsConstructor
  public class PersonService {
  
      private final PersonRepository personRepository;
  
      public Flux&lt;Person&gt; getAll() {
          return personRepository.findAll().switchIfEmpty(Flux.empty());
      }
  
      public Mono&lt;Person&gt; getById(final String id) {
          return personRepository.findById(id);
      }
  
      public Mono update(final String id, final Person person) {
          return personRepository.save(person);
      }
  
      public Mono save(final Person person) {
          return personRepository.save(person);
      }
  
      public Mono delete(final String id) {
          final Mono&lt;Person&gt; dbPerson = getById(id);
          if (Objects.isNull(dbPerson)) {
              return Mono.empty();
          }
          return getById(id).switchIfEmpty(Mono.empty()).filter(Objects::nonNull).flatMap(personToBeDeleted -&gt; personRepository
                  .delete(personToBeDeleted).then(Mono.just(personToBeDeleted)));
      }
  }
  </code></pre>
  
  <p>I understand everything except the <code>save</code> and <code>update</code> methods. I don't understand why we use <code>flatMap</code> in this situation.
  Why is this so, and how can I write the implementation of the <strong>update</strong> method in my <strong>Handler</strong>.</p>
  
  <h2>Updated</h2>
  
  <p>Let's see the method <strong>save()</strong> in Handler</p>
  
  <pre><code>public Mono&lt;ServerResponse&gt; save(ServerRequest request) {
          final Mono&lt;Person&gt; person = request.bodyToMono(Person.class);
          return ok()
                  .contentType(MediaType.APPLICATION_JSON)
                  .body(fromPublisher(person.flatMap(personService::save), Person.class));
      }
  </code></pre>
  
  <p>I think the fact is that we have already received:</p>
  
  <pre><code>final Mono&lt;Person&gt; person = request.bodyToMono(Person.class);
  </code></pre>
  
  <p>and then we do:</p>
  
  <pre><code>personService::save
  </code></pre>
  
  <p>As a result, we get Mono&lt; Mono&lt; Person>></p>
  
  <p>flatMap is just like map, except that it unpacks the return value of the lambda given if the value is itself contained in a <code>Publisher&lt;T&gt;</code>. In our case, the <code>personService.save(T)</code> method returns a <code>Mono&lt;T&gt;</code>. If we’d used map instead of <code>flatMap(T)</code>, we’d have a <code>Mono&lt; Mono&lt; T&gt;&gt;</code>, when what we really want is a <code>Mono&lt;T&gt;</code>. We can cleanly solve this problem using flatMap.</p>
  
  <p>Am I right or is this statement wrong?</p>