Empty Monoの処理方法

2456 ワード

Reactorプログラミングでは、empty Monoに対して特定のビジネスロジックを行う必要がある場合があります.reactorでプログラミングされていないコードを見てみましょう.
public void oldCheck(Token token) {
  if (token == null) {
    // business logic
    return;
  }
  if (token.isExpired) {
    // business logic
    return;
  }
  // business logic
  return;
}

reactorに変えるとこうなるかもしれません
public Mono badCheck(Mono tokenMono) {
  return tokenMono
      .flatMap(token -> {
        if (token == null) {
          // CAUTION: You will never be in here
          // business logic
          return Mono.empty();
        }
        if (token.isExpired) {
          // business logic
          return Mono.empty();
        }
        // business logic
        return Mono.empty();
      });
}

上記の例示的なコードの注釈は、if (token == null) {}がemptyである場合、Monoがトリガされないため、flatMapと書かれている.flatMapのようなほとんどのOperatorは、Publisher(MonoおよびFluxPubisher)のプッシュデータに依存しており(詳細はjavadocを参照)、Publisher自体にデータがプッシュできない場合、Operatorはトリガーされません.言い換えればflatMap内部でnullを得ることは不可能である.
では、どうすればいいですか.Java 8のOptionalを中間値として使用できます.
public Mono goodCheck(Mono tokenMono) {
  return tokenMono
      // Transform Mono to Mono>.
      // If Mono is empty, flatMap will not be triggered,
      // then we will get a empty Mono>
      .flatMap(token -> Mono.just(Optional.of(token)))
      // If Mono> is empty, provide an empty Optional,
      // then we will get a non-empty Mono> anyway
      .defaultIfEmpty(Optional.empty())
      // Since Mono> is not empty, flatMap will always be triggered.
      .flatMap(tokenOptional -> {
        if (!tokenOptional.isPresent()) {
          // business logic
          return Mono.empty();
        }
        Token token = tokenOptional.get();
        if (token.isExpired) {
          // business logic
          return Mono.empty();
        }
        // business logic
        return Mono.empty();
      });
}
defaultIfEmptyに加えて、Reactorは、empty switchIfEmpty/repeatWhenEmptyを処理するためにMonoFluxを提供する.