CompleatableFuture可以在handle方法中异常完成吗?

Can CompleatableFuture be completed exceptionally in handle method?

我正在尝试将存储库异常映射到服务异常。这样的做法好吗?

@Override
public CompletableFuture<Void> delete(String id, Map<String, String> headers) {
  CompletableFuture<Void> future = repository.delete(id, headers);
  return future.handle((aVoid, throwable) -> {
    if (throwable != null) {
      Throwable cause = throwable.getCause();
      if (DbExcUtils.isFKViolation(throwable)) {
        future.completeExceptionally(new BadRequestException(HAS_ASSIGNED_RECORDS_MESSAGE));
      } else {
        future.completeExceptionally(cause);
      }
    }
    return aVoid;
  });
}

方法 handle 只会在目标 CompletableFuture 实例完成时调用它给定的 BiFunction

Returns a new CompletionStage that, when this stage completes either normally or exceptionally, is executed with this stage's result and exception as arguments to the supplied function.

从这个意义上说,你无法再次完成它。 completeExceptionally 的 javadoc 状态

If not already completed, causes invocations of get() and related methods to throw the given exception.

当 future 已经完成时,它本质上是一个空操作。

如果你只想映射异常类型,那么使用exceptionally

Returns a new CompletionStage that, when this stage completes exceptionally, is executed with this stage's exception as the argument to the supplied function. Otherwise, if this stage completes normally, then the returned stage also completes normally with the same value.

这似乎在做您正在尝试的事情,即。如果有异常,则映射异常,否则 return 结果。

例如,

return future.exceptionally(throwable -> {
    Throwable cause = throwable.getCause();
    if (DbExcUtils.isFKViolation(throwable)) {
        throw new CompletionException(new BadRequestException(HAS_ASSIGNED_RECORDS_MESSAGE));
    } else {
        throw new CompletionException(cause);
    }
});

请注意,我们抛出了新的异常。

此外,您可能需要检查 throwable 是否是 CancellationException(无原因)并在执行映射逻辑之前重新抛出它。


你可以使用obtrudeException,但我不推荐它

Forcibly causes subsequent invocations of method get() and related methods to throw the given exception, whether or not already completed. This method is designed for use only in error recovery actions, and even in such situations may result in ongoing dependent completions using established versus overwritten outcomes.