6

Having following scratch code:

  public static void main(String[] args) throws ExecutionException, InterruptedException {

    CompletableFuture<Void> process1 = CompletableFuture.runAsync(() -> {
      System.out.println("Process 1 with exception");
      throw new RuntimeException("Exception 1");
    });

    CompletableFuture<Void> process2 = CompletableFuture.runAsync(() -> {
      System.out.println("Process 2 without exception");
    });

    CompletableFuture<Void> process3 = CompletableFuture.runAsync(() -> {
      System.out.println("Process 3 with exception");
      throw new RuntimeException("Exception 3");
    });

    CompletableFuture<Void> allOfProcesses = CompletableFuture.allOf(process1, process2, process3);

    allOfProcesses.get();
  }

I'm looking for way how to collect all exceptions which have been thrown during parallel execution in CompletableFuture.allOf() and map it to List.

I know I can do this by returning exception (CompletableFuture<Exception>) instead of throwing and collect it by using CompletableFuture::join but I think throwing exception approach is better than returning and throwing it later

Kamil W
  • 2,230
  • 2
  • 21
  • 43

1 Answers1

8

If you want to avoid returning CompletableFuture<Exception> and just be able to first throw and than still be able to do something will exception collected from all of the CompletableFutures.

In that case you can use CompletableFuture::exceptionally to collect the exceptions:

private static List<Throwable> collectedExceptions = Collections.synchronizedList(new ArrayList<>());

public static void main(String[] args) throws ExecutionException, InterruptedException {

    CompletableFuture<Void> process1 = CompletableFuture.runAsync(() -> {
        System.out.println("Process 1 with exception");
        throw new RuntimeException("Exception 1");
    }).exceptionally(exception -> {
        // Handle your exception here
        collectedExceptions.add(exception);
        return null;
    });

    CompletableFuture<Void> process2 = CompletableFuture.runAsync(() -> {
        System.out.println("Process 2 without exception");
    });

    CompletableFuture<Void> process3 = CompletableFuture.runAsync(() -> {
        System.out.println("Process 3 with exception");
        throw new RuntimeException("Exception 3");
    }).exceptionally(exception -> {
        // Handle your exception here
        collectedExceptions.add(exception);
        return null;
    });

    CompletableFuture<Void> allOfProcesses = CompletableFuture.allOf(process1, process2, process3);

    allOfProcesses.get();
    assert (collectedExceptions.size() == 2);
}
syntagma
  • 23,346
  • 16
  • 78
  • 134