处理可调用内部的Future.get()自定义异常的最干净/正确的方法是什么? (高级)

时间:2018-10-03 18:36:05

标签: java exception

代码:

  public void processData(PaymentRequest data) {
    List<Payment> paymentList = new ArrayList<>();
    List<Callable<Payment>> paymentCallables = new ArrayList<>();

    data.getPaymentInfoList().forEach(payment -> paymentCallables.add(() -> payment.execute()));

    try {
      executorService.invokeAll(paymentCallables)
              .stream()
              .map(this::apply)
              .forEach(paymentList::add);
    } catch (InterruptedException exception) {
      throw new ProcessorException("task interrupted when processing", exception);
    }
  }

  private Payment apply(Future<Payment> paymentFuture) {
    try {
      return paymentFuture.get(); //Only shows ExecutuonException
    } catch (InterruptedException | ExecutionException exception) {
      throw new ProcessorException("task interrupted or failed", exception);
    }
  }

为清楚起见,我省略了一些代码。

背景信息

我的系统有一个可调用列表。在此列表中,有些执行将在以后执行。 需要注意的关键是,将要运行的执行程序内部具有自定义异常。

代码运行时,其中一个可调用执行中存在异常。引发异常; 具体来说,此异常发生在paymentFuture.get()。

问题

我在payment.execute()中有自己的自定义异常。例如,我在payments.execute()方法中有一个验证异常。示例:

public void execute() {
try {
//process
} catch (
throw new ValidationException();
}

问题是,当发生此异常并抛出ValidationException时,此异常将被ExecutionException包裹。因此,正在处理的是ExecutionException。因此,java在我的ValidationExecption周围包装了ExecutionException。我想要的是一种处理并从类中抛出ValidationException的方法,以便可以由另一个类GlobalExceptionHandler对其进行处理。

PS: 正在做:

throw exception.getCause()

将无法工作,因为需要在方法中使用try / catch处理异常,而我想抛出一个可以由外部类捕获的新异常。

曾经试图将其整理几个小时,所以我对所有想法都开放。

1 个答案:

答案 0 :(得分:1)

我相信payment.execute方法可能引发的异常可以通过一个通用接口进行分组,例如PaymentException

ValidationException将扩展PaymentException

在这种情况下,如果条件为exception.getCause() instanceof PaymentException,则需要检查true并重新抛出原因。

try {
    return paymentFuture.get();
} catch (InterruptedException | ExecutionException exception) {
    final Throwable cause = exception.getCause();
    if (cause instanceof PaymentException) {
       throw (PaymentException) cause;
    }
    throw new ProcessorException("task interrupted or failed", exception);
}