0

I would like to know what is the appropriate way obtaining an object from a Mono (or Flux) to pass onto a non-reactive method such as a JpaRepository.

Here is the way I did it:

@Service
public class ReactiveAccountService {

    //AccountService's methods take non-mono/non-flux objects as arguments
    private AccountService accountService;

    public ReactiveAccountService(AccountService accountService) {
        this.accountService = accountService;
    }

    public Mono<Void> signUp(Mono<Account> accountMono) {
        //Account is a Jpa entity
        accountMono.subscribe(account -> accountService.signUp(account));
        return Mono.empty();
    }

}

How can this be improved? Can someone please advise?

Brian Clozel
  • 56,583
  • 15
  • 167
  • 176
balteo
  • 23,602
  • 63
  • 219
  • 412
  • If I try to use `block()`, I get the following error: `block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-3` – balteo Sep 14 '18 at 13:07
  • This reply from Brian Clozel provides interesting insights: https://stackoverflow.com/a/51456050/536299 – balteo Sep 14 '18 at 13:27
  • The only trouble is that in my case I have to deal with blocking method calls (`JpaRepository` via the plain `AccountService`). – balteo Sep 14 '18 at 13:51
  • Any advice would be very welcome – balteo Sep 14 '18 at 13:57

1 Answers1

1

The better way to do that is like this:

public Mono<Void> signUp(Mono<Account> accountMono) {
    //Account is a Jpa entity
    return accountMono.flatMap(account -> {
                  accountService.signUp(account);
                  return Mono.empty();
              });
}

This way you follow Reactive Streams requirements and don't bother the execution flow with your blocking code. Plus according the Spring WebFlux requirements you don't subscribe in your own code, but deffer everything to the container which is an initiator of that Mono<Account>. The actual execution will happen, when there is enough resources in the Web (Reactive) container to subscribe to the returned Mono.

Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
  • if the `AccountService` is doing blocking I/O (like calling a JPA repository it seems), won't that block a server thread and create issues at runtime? Shouldn't we try to wrap that blocking operation instead and schedule it on another thread? – Brian Clozel Sep 17 '18 at 08:14
  • I think if answer is accepted, then it works well. At least for the reporter. We need to investigate it under the heavy load load though... – Artem Bilan Sep 17 '18 at 12:51
  • Could you point out where in the documentation they say not to subscribe on your own? I do understand well why you shouldn't do it, but such a link would be good to show to others and, frankly, I have a difficulties with finding such remark in docs. – wst Dec 26 '18 at 02:31