[英]How to throw a custom exception from CompletableFuture?
Question: how can I directly throw a custom exception from .exceptionally()
? 问题:如何直接从.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());
}
Problem: I just always get a CompletionException
whose ex.getCause()
is instanceof BadRequestException
. 问题:我总是得到一个CompletionException
其ex.getCause()
是BadRequestException
instanceof。
Is that possible at all? 这有可能吗?
As said by Didier L , exceptions thrown by the functions (or generally exceptions that completed a CompletableFuture
) are always wrapped in a CompletionException
(unless they are already a CompletionException
or CancellationException
). 正如Didier L所说,函数抛出的异常(或者通常是完成 CompletableFuture
异常 )总是包含在CompletionException
(除非它们已经是CompletionException
或CancellationException
)。
But note that your code becomes much simpler when not even trying to translate the exception via exceptionally
: 但请注意,甚至在尝试通过exceptionally
转换异常时,您的代码变得更加简单:
List<CompletableFuture<Object>> futures =
tasks.stream()
.map(task -> CompletableFuture.supplyAsync(() -> businessLogic(task)))
.collect(Collectors.toList());
try {
List<Object> results = futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList());
} catch (CompletionException e) {
throw e.getCause() instanceof BusinessException?
new BadRequestException("at least one async task had an exception"): e;
}
or 要么
… catch (CompletionException e) {
throw e.getCause() instanceof BusinessException?
new BadRequestException("at least one async task had an exception"):
e.getCause() instanceof BusinessException? (RuntimeException)e.getCause(): e;
}
Since exceptionally
's primary purpose is translating an exception to a non-exceptional result value, using it for translating the exception to another thrown exception was not the best fit anyway and it also needed an instanceof
. 由于exceptionally
的主要目的是将异常转换为非异常结果值,因此使用它将异常转换为另一个抛出的异常并不是最合适的,它还需要一个instanceof
。 So performing this translation in the catch
clause saves you from another translation step. 因此,在catch
子句中执行此转换将使您免于另一个转换步骤。
This is not possible. 这是不可能的。 The Javadoc of join()
clearly states: join()
的Javadoc明确指出:
Returns the result value when complete, or throws an (unchecked) exception if completed exceptionally. 完成后返回结果值,如果异常完成则抛出(未经检查的)异常。 To better conform with the use of common functional forms, if a computation involved in the completion of this CompletableFuture threw an exception, this method throws an (unchecked)
CompletionException
with the underlying exception as its cause. 为了更好地符合常用函数形式的使用, 如果完成此CompletableFuture所涉及的计算引发异常,则此方法将抛出(未经检查的)CompletionException
,并将基础异常作为其原因。
(emphasis is mine) (重点是我的)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.