弹簧反应堆中的错误处理未按预期工作

时间:2018-12-26 10:37:50

标签: java spring project-reactor

即使tryDemo方法抛出NPE,我也无法弄清楚为什么doOnError代码没有得到执行。我试图了解反应式编程中的错误处理,对此我是陌生的

Mono.zip( Mono.fromCallable( ()->tryDemo()), Mono.fromCallable( ()-   >tryDemo1()),Mono.fromCallable(()-> tryDemo2() ))
        .flatMap( data -> Mono.just( Tuples.of( data.getT1(), data.getT2(),data.getT3() ) ) )
        .doOnError( e -> log.error( "Error {}", e.getStackTrace() ) )
        .subscribe(T->{log.info("Tuple {}",T.getT2()  );});



public Mono<String> tryDemo() {
    log.info( "Data--1" );

    return Mono.error( NullPointerException::new );
    //return Mono.just( "1" );
}

15:56:07.023 [main] INFO com.infosys.rtbm.Test - Data--1
15:56:07.027 [main] INFO com.infosys.rtbm.Test - Tuple MonoJust

1 个答案:

答案 0 :(得分:3)

别忘了订阅我

在您的示例中,您返回错误Mono。这里最棘手的部分是fromCallable期望您返回标量值。

如果我们查看Mono.fromCallable的API,就会发现可接受的参数是

public static <T> Mono<T> fromCallable(Callable<? extends T> supplier)

这意味着如果我们的Callable返回Mono,我们将得到

Mono<Mono<Object>> monoOfMono = Mono.fromCallable(() -> 
     Mono.error(NullPointerException::new)
);

因此,如果我们需要产生一个错误,我们必须直接在lambda中抛出该异常

Mono<Object> justMono = Mono.fromCallable(() -> {
     throws new NullPointerException()
});

总结一下,Mono.fromCallable不会尝试检查返回类型是否为流。因此,您的Mono被认为是正常的标量值,并向下游传播。因此,要解决此问题,您可以执行以下操作:

在您的tryDemo方法中引发异常:

Mono.zip( Mono.fromCallable( ()->tryDemo()), Mono.fromCallable( ()-   >tryDemo1()),Mono.fromCallable(()-> tryDemo2() ))
    .flatMap( data -> Mono.just( Tuples.of( data.getT1(), data.getT2(),data.getT3() ) ) )
    .doOnError( e -> log.error( "Error {}", e.getStackTrace() ) )
    .subscribe(T->{log.info("Tuple {}",T.getT2()  );});



public String tryDemo() {
    log.info( "Data--1" );

    throw new NullPointerException();
    //return "1";
}

fromCallable替换为defer

您可以使用fromCallable运算符来实现您想通过Mono.defer实现的懒惰,在这种情况下,该运算符期望Mono是lambda的返回类型。

如果我们查看该操作员的API,我们将观察以下内容

public static <T> Mono<T> defer(Supplier<? extends Mono<? extends T>> supplier);

在这种情况下,我们有Supplier恰好期望某事Mono作为返回类型,因此,一旦再次尝试您的初始代码,您将实现预期的行为:

Mono<Object> justMono = Mono.defer(() -> 
     Mono.error(NullPointerException::new)
);

在这种情况下,一旦供应商退回MonoMono.defere就会订阅它并收到错误信号:

Mono.zip( 
        Mono.defer(() -> tryDemo()), 
        Mono.defer(() -> tryDemo1()),
        Mono.defer(() -> tryDemo2())
    )
    .flatMap(data -> Mono.just(Tuples.of( 
         data.getT1(), 
         data.getT2(), 
         data.getT3()
    )))
    .doOnError( e -> log.error( "Error {}", e.getStackTrace() ) )
    .subscribe(T -> {
        log.info("Tuple {}",T.getT2()  );
    });