【发布时间】:2023-03-10 08:56:01
【问题描述】:
我对 onErrorContinue() 有一个问题,即传递给 Biconsumer 的对象为空。
我正在使用 Spring boot 2.1.13.RELEASE 和响应式 mongo,反应堆核心版本为 3.2.15.RELEASE。
当调用数据库以检索具有 id 的记录并使用运算符 switchIfEmtpy() 我使用 Mono.error() 抛出异常并且下游我尝试使用 onErrorContinue( )。
下面的代码解释了这个问题:
public static void main(String[] args) {
Flux.range(1, 10)
.flatMap(integer -> mapInteger(integer))
.doOnNext(System.out::println)
.onErrorContinue((throwable, o) -> System.out.println("error with " + o)) // o is null
.subscribe();
}
public static Mono<Integer> mapInteger(Integer num) { // This is here to simulate the db call
return Mono.just(num)
.flatMap(t -> {
if (t == 5)
return Mono.empty();
else
return Mono.just(num * 2);
})
.switchIfEmpty(Mono.error(new RuntimeException("Error happened while mapping integer!")));
}
这将打印以下值:
2
4
6
8
error with null
12
14
16
18
20
PS。当流中发生另一个错误时,我没有问题。
更新: mapInteger() 用于模拟以下对响应式mongo 存储库的调用:
public Mono<MetaData> getFromDbByKey(String key) {
return repository
.findByKeyAndDeletedIsFalse(key)
.switchIfEmpty(Mono.error(() -> new RuntimeException()));
}
并且对 getFromDbByKey() 的调用返回这个元数据,我需要将它映射到主流程中的通量。
通过 onErrorContinue,我们捕获 Throwable,并根据其类型对每种类型的错误进行不同的处理。
【问题讨论】:
-
作为一种解决方法,您可以更改代码:
.flatMap(t -> { if (t == 5) throw new RuntimeException("Error happened while mapping integer value " + t);,您可以在onErrorContinue中记录此异常消息 -
onErrorContinue是高级运算符,您是否 100% 确定需要它并且不能使用其他onError处理程序之一? (包括flatMap内,附加到mapInteger) -
null来自这样一个事实,即在出现错误的地方,发生的唯一信号是onComplete。所以没有数据信号传递给处理程序,因此null -
@VasylSarzhynskyi 感谢您的评论。不幸的是,我不能这样做......我还更新了帖子以澄清为什么我不能这样做,因为在我的真实代码中它是对数据库的调用
-
@SimonBaslé 感谢您的解释。是的,我们需要使用它,因为我们处理错误的方式不同……在某些情况下,我们会保存到数据库中,稍后调度程序会决定要做什么,而在其他一些情况下,日志就足够了。学院建议的另一个解决方案是创建一个自定义 RuntimeException 并将导致问题的对象包含在其中。
标签: java spring-boot spring-webflux project-reactor reactive