2017-08-17 1 views
0

Ich benutze Spring Reactor 3.1.0.M3 und habe einen Anwendungsfall, wo ich Monos aus mehreren Quellen zusammenführen muss. Ich fand, dass, wenn eines der Monos ein leeres Mono ist, zip ohne Fehler fehlschlägt.Spring Reactor: Mono.zip schlägt auf leer Mono

Beispiel:

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()); 

Wenn m3 zugesetzt wird, wird der Kombinator in der Antwort übersprungen ist null. Wenn ich m3 entferne, funktioniert alles wie erwartet und "AB" wird zurückgegeben. Gibt es eine Möglichkeit, das zu umgehen, indem ich das leere Mono erkenne? Gibt es auch eine Möglichkeit, dass die Kombinator-Methode den Typ des Objekts kennt, anstatt zu casten?

+0

für eine kleine Anzahl von Mono gibt es Mono.when (wir denken darüber nach, das in 3.1.0 zu ändern). Es wird nicht das Empy-wenn-eine-Quelle-leere Verhalten obwohl ... –

+0

Ich habe nur 3 Monos in diesem Beispiel, aber in der tatsächlichen Code verwende ich Iterable. Also wäre es nützlich, wenn ich leere Monos herausfiltern oder irgendwie damit umgehen könnte. Im Moment löst sich das kombinierte Mono auf Null auf, ohne dass die Ursache angegeben wird. Wenn Monos von mehreren Quellen produziert werden, gibt es keine Garantie, dass keine leer sein würde. – athom

Antwort

1

Der Zip-Operator verhält sich nicht so. Es wäre in der Tat kontraintuitiv: Ihr Code erwartet ein Tuple von 3 Elementen und Sie bekommen nur zwei?!?

In diesem Fall haben Sie die Kontrolle und nur Sie können entscheiden, was ein guter Standardwert ist, wenn keiner bereitgestellt wird (denken Sie daran, null Werte sind durch die reaktive Streams-Spezifikation verboten).

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(); 
}); 

bearbeiten

Sie scheinen von der Natur eines Publisher Art verwechselt werden, siehe:

, wenn einer der Monos eine leere Mono ist, schlägt zip ohne einen Fehler

und

Also, wenn ich war und zip Monos, um zu versuchen und aus irgendeinem Grund ein leer ist, würde die zip scheitern, und ich kann nicht gegen diese

Eine leere Mono zu sichern in jedem Code zu setzen scheinen kein Fehlerfall : Es wird nur kein Wert ausgegeben und es wird erfolgreich abgeschlossen. Sie können das überprüfen, indem Sie das Codebeispiel zu ändern:

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 
    }); 

Also je nach Ihren Anforderungen können Sie:

  • einen defaultIfEmpty Betreiber auf diesen 3 Mono Instanzen anwenden, wenn es bequem sind Standardwerte können Sie verlassen sich auf
  • anwenden einen defaultIfEmpty Operator auf dem kombinierten Mono, mit einem Standardwert, oder sogar, dass in einer Fehlermeldung Transformation mit combined.switchIfEmpty(Mono.error(...))
+0

Ich versuche zu verstehen, wie dies in einer Umgebung mit mehreren Produzenten von Mono nicht unter meiner Kontrolle funktionieren würde.Also wenn ich versuchen würde, Monos zu zippen und aus irgendeinem Grund ist einer leer, würde der Zip fehlschlagen und ich könnte keinen Code einfügen, um dagegen zu schützen. Ich benutze Reactor 3.1.0.M3, die nicht mit der Signatur in Ihrem Beispiel zip haben scheint – athom

+0

Ich habe meine Antwort bearbeitet, um die Tatsache zu unterstreichen, dass ein leeres Mono kein Fehlerfall ist –