web-dev-qa-db-ja.com

Spring Reactor:空のMonoでMono.Zipが失敗する

Spring Reactor 3.1.0.M3を使用していて、複数のソースからMonoをマージする必要がある使用例があります。 Monoの1つが空のMonoの場合、Zipはエラーなしで失敗することがわかりました。

例:

Mono<String> m1 = Mono.just("A");
Mono<String> m2 = Mono.just("B");
Mono<String> m3 = Mono.empty();

Mono<String> combined = Mono.Zip(strings -> {
    StringBuffer sb = new StringBuffer();
    for (Object string : strings) {
        sb.append((String) string);
    }
    return sb.toString();
}, m1, m2, m3);
System.out.println("Combined " + combined.block());

M3が追加されると、レスポンスがnullの場合、コンビネータはスキップされます。 m3を削除すると、すべて正常に機能し、「AB」が返されます。空のモノを検出してこれを処理できる方法はありますか?また、キャストする代わりに、combinatorメソッドにオブジェクトのタイプを知らせる方法はありますか?

9
athom

Zipオペレーターは、このように動作しません。それは実際には直観に反するでしょう:あなたのコードは3つの要素のタプルを期待していて、あなたは2つしか得ていません!?

この場合、あなたが管理し、何も提供されない場合に適切なデフォルト値を決定できるのはあなただけです(null値はリアクティブストリームの仕様で禁止されていることに注意してください)。

_Mono<String> m1 = Mono.just("A");
Mono<String> m2 = Mono.just("B");
Mono<String> m3 = Mono.empty().defaultIfEmpty("");

Mono<String> combined = Mono.when(m1, m2, m3).map(t -> {
    StringBuffer sb = new StringBuffer();
    sb.append(t.getT1());
    sb.append(t.getT2());
    sb.append(t.getT3());
    return sb.toString();
});
_

編集する

Publisherタイプの性質に混乱しているようです。以下を参照してください:

monoの1つが空のMonoである場合、Zipはエラーなしで失敗します

そして

したがって、Zip Monoを試してみると、何らかの理由でZip Monoが空の場合、Zipは失敗し、それを防ぐためのコードを挿入することができません。

空のMonoは失敗のケースではありません。値が出力されず、正常に完了しただけです。コードサンプルを変更することで確認できます。

_    combined.subscribe(
            s -> System.out.println("element: " + s), // doesn't execute
            s -> System.out.println("error: " + s), // doesn't execute
            () -> { System.out.println("complete!"); // prints
    });
_

したがって、要件に応じて、次のことができます。

  • これらの3つのdefaultIfEmptyインスタンスにMono演算子を適用します。信頼できる便利なデフォルト値がある場合
  • 結合されたdefaultIfEmptyにデフォルト値を使用してMono演算子を適用するか、combined.switchIfEmpty(Mono.error(...))でエラーメッセージに変換します
16
Brian Clozel

Mono.Zip

ソースのエラーまたは空の完了により、他のソースがキャンセルされ、結果のMonoがそれぞれすぐにエラーまたは完了します。

Monoソースが値なしで完了したときに、他のソースの実行を続行したい場合は、Mono.zipDelayErrorが最適です。

0