Close

Java 12 - CompletionStage's new methods for exception handling

[Updated: Apr 2, 2019, Created: Apr 2, 2019]

Java 12 added new exception handling methods in CompletionStage. Also check out the existing API for exception handling in CompletionStage.

Async exception handling

Existing method to handle exception:

CompletionStage<T> exceptionally(Function<Throwable,? extends T> fn)

New methods to handle exception asynchronously:

CompletionStage<T> exceptionallyAsync(Function<Throwable,? extends T> fn)
CompletionStage<T> exceptionallyAsync(Function<Throwable,? extends T> fn, Executor executor)

Example

package com.logicbig.example;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class Ex1ExceptionallyAsync {
  public static void main(String[] args) throws Exception {
      ExecutorService executor = Executors.newSingleThreadExecutor();
      CompletableFuture.supplyAsync(() -> {
          printThreadInfo("division task");
          return 10 / 0;
      }).exceptionallyAsync(exception -> {
                  printThreadInfo("exceptionally Async");
                  System.err.println("exception: " + exception);
                  return 1;
              }, executor
      ).thenApply(input -> {
          printThreadInfo("multiply task");
          return input * 3;
      }).thenAccept(System.out::println);

      Thread.sleep(2000);//let the stages complete
      executor.shutdown();
  }

  private static void printThreadInfo(String desc) {
      System.out.printf("%s, Thread: %s%n", desc, Thread.currentThread().getName());
  }
}
division task, Thread: ForkJoinPool.commonPool-worker-3
exceptionally Async, Thread: pool-1-thread-1
exception: java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
multiply task, Thread: pool-1-thread-1
3

As seen above, exceptionally stage is invoked in a new thread.

Using old exceptionally() method:

package com.logicbig.example;

import java.util.concurrent.CompletableFuture;

public class Ex2ExceptionallyAsync {
  public static void main(String[] args) throws Exception {
      CompletableFuture.supplyAsync(() -> {
          printThreadInfo("division task");
          return 10 / 0;
      }).exceptionally(exception -> {
          printThreadInfo("exceptionally Async");
          System.err.println("exception: " + exception);
          return 1;
      }).thenApply(input -> {
          printThreadInfo("multiply task");
          return input * 3;
      }).thenAccept(System.out::println);

      Thread.sleep(2000);
  }

  private static void printThreadInfo(String desc) {
      System.out.printf("%s, Thread: %s%n", desc, Thread.currentThread().getName());
  }
}
division task, Thread: ForkJoinPool.commonPool-worker-3
exceptionally Async, Thread: ForkJoinPool.commonPool-worker-3
exception: java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
multiply task, Thread: ForkJoinPool.commonPool-worker-3
3

Composing Exceptionally

Each of the following new methods returns a new CompletionStage that, when this stage completes exceptionally, is composed using the results of the supplied function applied to this stage's exception. (Also check out existing API of Composing completion stages)

CompletionStage<T> exceptionallyCompose(Function<Throwable,? extends CompletionStage<T>> fn)
CompletionStage<T> exceptionallyComposeAsync(Function<Throwable,? extends CompletionStage<T>> fn)
CompletionStage<T> exceptionallyComposeAsync(Function<Throwable,? extends CompletionStage<T>> fn, Executor executor)

Example

package com.logicbig.example;

import java.util.concurrent.CompletableFuture;

public class Ex3ExceptionallyCompose {
  public static void main(String[] args) {
      CompletableFuture<Integer> completableFuture = CompletableFuture
              .supplyAsync(() -> {
                  return 10 / 0;
              });
      CompletableFuture<Integer> completableFuture2 = CompletableFuture
              .supplyAsync(() -> 1);

      CompletableFuture<Integer> exceptionallyCompose = completableFuture
              .exceptionallyCompose(throwable -> {
                  System.err.println("exception: " + throwable);
                  return completableFuture2;
              });
      exceptionallyCompose.thenApply(i -> i * 3)
                          .thenAccept(System.out::println);
  }
}
exception: java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
3

Example Project

Dependencies and Technologies Used:

  • JDK 12
CompletionStage new methods for exception handling Select All Download
  • java-12-completion-stage-changes
    • src
      • com
        • logicbig
          • example
            • Ex1ExceptionallyAsync.java

    See Also