简体   繁体   English

如何将异常集合作为根本原因传递?

[英]How can I pass a collection of exceptions as a root cause?

Some method, myMethod , invokes several parallel executions and awaits their terminations.某些方法myMethod调用多个并行执行并等待它们的终止。

These parallel executions can finish with exceptions.这些并行执行可以以异常结束。 So myMethod gets an exception list.所以myMethod得到一个例外列表。

I want to pass the exception list as a root cause, but the root cause might be only a single exception.我想将异常列表作为根本原因传递,但根本原因可能只是一个异常。 Sure I can create my own exception to achieve what I want, but I want to know if Java, Spring, or Spring Batch has something like this out of the box.当然我可以创建自己的异常来实现我想要的,但我想知道 Java、Spring 或 Spring Batch 是否有类似的东西。

I'm not sure I'd do it (though given the JavaDoc I couldn't tell you why I hesitate), but there is the list of suppressed exceptions on Throwable , which you can add to via addSuppressed .我不确定我是否会这样做(尽管考虑到 JavaDoc,我无法告诉你我为什么犹豫),但是Throwable上有抑制异常的列表,你可以通过addSuppressed添加它。 The JavaDoc doesn't seem to say this is only for the JVM to use in try-with-resources: JavaDoc 似乎并没有说这仅适用于 JVM 在 try-with-resources 中使用:

Appends the specified exception to the exceptions that were suppressed in order to deliver this exception.将指定的异常附加到为传递此异常而被抑制的异常。 This method is thread-safe and typically called (automatically and implicitly) by the try-with-resources statement.此方法是线程安全的,通常由 try-with-resources 语句调用(自动和隐式)。

The suppression behavior is enabled unless disabled via a constructor.除非通过构造函数禁用,否则会启用抑制行为。 When suppression is disabled, this method does nothing other than to validate its argument.当抑制被禁用时,这个方法除了验证它的参数之外什么都不做。

Note that when one exception causes another exception, the first exception is usually caught and then the second exception is thrown in response.请注意,当一个异常导致另一个异常时,通常会捕获第一个异常,然后抛出第二个异常作为响应。 In other words, there is a causal connection between the two exceptions.换句话说,这两个例外之间存在因果关系。 In contrast, there are situations where two independent exceptions can be thrown in sibling code blocks, in particular in the try block of a try-with-resources statement and the compiler-generated finally block which closes the resource.相反,在某些情况下,可以在同级代码块中引发两个独立的异常,特别是在 try-with-resources 语句的 try 块和关闭资源的编译器生成的 finally 块中。 In these situations, only one of the thrown exceptions can be propagated.在这些情况下,只能传播引发的异常之一。 In the try-with-resources statement, when there are two such exceptions, the exception originating from the try block is propagated and the exception from the finally block is added to the list of exceptions suppressed by the exception from the try block.在 try-with-resources 语句中,当有两个这样的异常时,将传播源自 try 块的异常,并将 finally 块的异常添加到由 try 块的异常抑制的异常列表中。 As an exception unwinds the stack, it can accumulate multiple suppressed exceptions.当一个异常展开堆栈时,它可以累积多个被抑制的异常。

An exception may have suppressed exceptions while also being caused by another exception.一个异常可能已经抑制了异常,同时也由另一个异常引起。 Whether or not an exception has a cause is semantically known at the time of its creation, unlike whether or not an exception will suppress other exceptions which is typically only determined after an exception is thrown.异常是否有原因在其创建时在语义上是已知的,这与异常是否会抑制其他异常不同,这通常仅在抛出异常后才确定。

Note that programmer written code is also able to take advantage of calling this method in situations where there are multiple sibling exceptions and only one can be propagated.请注意,程序员编写的代码也能够在存在多个同级异常且只能传播一个异常的情况下调用此方法。

Note that last paragraph, which seems to suit your case.请注意最后一段,这似乎适合您的情况。

Exceptions and their causes are always only a 1:1 thing: you can throw one exception and each exception can only have one cause (which can again have one cause...).异常及其原因始终只是 1:1 的事情:您可以抛出一个异常,并且每个异常只能有一个原因(也可以有一个原因......)。

That could be considered a design fault, especially when considering multi-threaded behaviour as you described.这可能被认为是设计错误,尤其是在考虑您所描述的多线程行为时。

That's one of the reasons why Java 7 added addSuppressed to throwable which can basically attach an arbitrary amount of exceptions to a single other one (the other primary motivation was try-with-resources which needed a way to handle exceptions in the finally block without silently dropping them).这就是为什么 Java 7 将addSuppressed添加到 throwable 的原因之一,它基本上可以将任意数量的异常附加到另一个异常(另一个主要动机是 try-with-resources 需要一种方法来处理 finally 块中的异常而无需静默丢弃它们)。

So basically when you have 1 exception that causes your process to fail, you add that one as the cause of your higher-level exception, and if you have any more, then you add those to the original one using addSuppressed .因此,基本上,当您有 1 个导致进程失败的异常时,您可以将该异常添加为更高级别异常的原因,如果还有更多异常,则使用addSuppressed将它们添加到原始异常中。 The idea is that that first exception "supressed" the others becoming a member of the "real exception chain".这个想法是,第一个异常“压制”了其他异常成为“真正的异常链”的成员。

Sample code:示例代码:

Exception exception = null;
for (Foobar foobar : foobars) {
  try {
    foobar.frobnicate();
  } catch (Exception ex) {
    if (exception == null) {
      exception = ex;
    } else {
      exception.addSuppressed(ex);
    }
  }
}
if (exception != null) {
  throw new SomethingWentWrongException(exception);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM