【发布时间】:2018-08-08 09:07:29
【问题描述】:
问题:如何直接从.exceptionally() 抛出自定义异常?
List<CompletableFuture<Object>> futures =
tasks.stream()
.map(task -> CompletableFuture.supplyAsync(() -> businessLogic(task))
.exceptionally(ex -> {
if (ex instanceof BusinessException) return null;
//TODO how to throw a custom exception here??
throw new BadRequestException("at least one async task had an exception");
}))
.collect(Collectors.toList());
try {
List<Object> results = futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList());
} catch (CompletionException e) {
if (e.getCause() instanceof RuntimeException) {
throw (RuntimeException) e.getCause();
}
throw new RuntimeException(e.getCause());
}
问题:我总是得到一个CompletionException,其ex.getCause() 是instanceof BadRequestException。
这可能吗?
【问题讨论】:
-
我觉得不可能,每一个异常都会被包装成一个
CompletionException -
CompletableFuture最终将调用encodeThrowable(Throwable x),其中x是您的例外并返回new AltResult((x instanceof CompletionException) ? x : new CompletionException(x));- 因此您将始终得到CompletionException。我看到的唯一能直接得到你的例外的就是让它扩展CompletionException。 -
所以我必须将上面的代码包装在一个额外的
try {..} catch (CompletionException e)中并在外面重新抛出底层异常?请查看我的更新:这使得它非常样板,但可能没有更好的解决方案? -
也可以使用
ex.addSuppressed(new BadRequestException("at least one async task had an exception")),然后访问Arrays.stream(e.getSuppressed()).filter(...) -
这不是更少的样板......
标签: java java-stream completable-future