title: Spring Webflux with Spring MVC - nulls emitted when using doOnEach
body: <p>I'm experimenting a bit with Spring Webflux and Spring MVC, and encountered an interesting case.</p>
  
  <p>Starting with a simple controller:</p>
  
  <pre><code>@GetMapping
  public Mono&lt;String&gt; list(final Model model) {
      Flux&lt;User&gt; users = this.userRepository.findAll();
      model.addAttribute("users", users);
      return Mono.just("users/list");
  }
  </code></pre>
  
  <p>The <code>userReposutory</code> is a custom <code>ConcurrentHashMap</code>-based implementation. Here you can find the <code>findAll</code> method:</p>
  
  <pre><code>@Override
  public Flux&lt;User&gt; findAll() {
      return Flux.fromIterable(this.users.values());
  }
  </code></pre>
  
  <p>Whenever I try to return to access the "users/list" view, everything seems to be working properly.</p>
  
  <p>But, if I try to rewrite the controller using an idiomatic reactive approach, problems start appearing:</p>
  
  <pre><code>@GetMapping
  public Mono&lt;String&gt; list(final Model model) {
      return this.userRepository.findAll()
        .collectList()
        .doOnEach(users -&gt; model.addAttribute("users", users.get()))
        .map(u -&gt; "users/list");
  }
  </code></pre>
  
  <p>If I hit the endpoint, I'm getting this in logs:</p>
  
  <pre><code>java.lang.IllegalArgumentException: ConcurrentModel does not support null attribute value
      at org.springframework.util.Assert.notNull(Assert.java:193)
      at org.springframework.ui.ConcurrentModel.addAttribute(ConcurrentModel.java:75)
      at org.springframework.ui.ConcurrentModel.addAttribute(ConcurrentModel.java:39)
      at com.baeldung.lss.web.controller.UserController.lambda$list$0(UserController.java:37)
      at reactor.core.publisher.FluxDoOnEach$DoOnEachSubscriber.onError(FluxDoOnEach.java:132)
  </code></pre>
  
  <p>Apparently, some stray <code>null</code> is making its way there. Let's filter out all of them eagerly then:</p>
  
  <pre><code>@RequestMapping
  public Mono&lt;String&gt; list(final Model model) {
      return this.userRepository.findAll()
        .filter(Objects::nonNull)
        .collectList()
        .filter(Objects::nonNull)
        .doOnEach(users -&gt; model.addAttribute("users", users.get()))
        .map(u -&gt; "users/list");
  }
  </code></pre>
  
  <p>Same problem, but... if I squeeze everything in a <code>map()</code> call, everything works again:</p>
  
  <pre><code>@GetMapping
  public Mono&lt;String&gt; list(final Model model) {
      return this.userRepository.findAll()
        .collectList()
        .map(users -&gt; {
            model.addAttribute("users", users);
            return "users/list";
        });
  }
  </code></pre>
  
  <p>Although, placing side-effects in <code>map</code> is not optimal.</p>
  
  <p>Any ideas what's wrong with the <code>doOnEach()</code> here?</p>