Search code examples
javaspringspring-webfluxreactive-programmingproject-reactor

execute 2 Mono sequentialy not supporte blocking


i have the two bellow functions

Mono<Void> messageEvent(MessageEvent messageEvent);
Mono<Victim> getPersonById(String personId);

i want when the function messageEvent is executed successfully i executethe getPersonById function, and the return of the getPersonById function is saved in the database

i tried like below

    spi.messageEvent(message).doOnSuccess(it -> {
        spi.getPersonById(evt.getVictimId()).doOnSuccess(victim -> {
            repository.save(victim);
        }).block();
    }).block();

but i have this error

2023-03-09 21:56:20.191 ERROR 21080 --- [nister-group]-0] c.s.e.v.s.q.i : Exception in on() with cause = 'NULL' and exception = 'block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-2' java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-2 at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:83

)


Solution

  • You need this operator from Mono:

    /**
     * Let this {@link Mono} complete then play another Mono.
     * <p>
     * In other words ignore element from this {@link Mono} and transform its completion signal into the
     * emission and completion signal of a provided {@code Mono<V>}. Error signal is
     * replayed in the resulting {@code Mono<V>}.
     *
     * <p>
     * <img class="marble" src="doc-files/marbles/thenWithMonoForMono.svg" alt="">
     *
     * <p><strong>Discard Support:</strong> This operator discards the element from the source.
     *
     * @param other a {@link Mono} to emit from after termination
     * @param <V> the element type of the supplied Mono
     *
     * @return a new {@link Mono} that emits from the supplied {@link Mono}
     */
    public final <V> Mono<V> then(Mono<V> other) {
    

    So, in your code it probably could be like this:

     return spi.messageEvent(message)
         .then(spi.getPersonById(evt.getVictimId()))
         .map(repository::save);
    

    And yes: don't use block() in a Reactor Http thread.