@Test public void failingStage_multiCatch_correctHandlerTriggered() throws Exception { CompletableFuture<String> future = new CompletableFuture<>(); CompletableFuture<Integer> throwing = CompletableFutures.catchingCompose( CompletableFutures.catchingCompose( future.thenApply(str -> str.length() + Integer.parseInt(str)), NumberFormatException.class, error -> CompletableFuture.completedFuture(0)), NullPointerException.class, error -> CompletableFuture.completedFuture(1)); future.complete("foobar"); assertEquals(0, (int) throwing.get()); }
public static <T, E extends Throwable> CompletableFuture<T> catchingCompose( CompletableFuture<T> future, Class<E> exceptionClass, Function<? super E, ? extends CompletableFuture<T>> handler) { return future.handle( (value, error) -> { if (error == null) { return CompletableFuture.completedFuture(value); } else if (exceptionClass.isInstance(error.getCause())) { return handler.apply(exceptionClass.cast(error.getCause())); } else if (error instanceof CompletionException) { throw (CompletionException) error; } else { throw new AssertionError(error); } }) .thenCompose(wrapped -> wrapped); }
CompletableFutures { public static <T, E extends Throwable> CompletableFuture<T> catchingCompose( CompletableFuture<T> future, Class<E> exceptionClass, Function<? super E, ? extends CompletableFuture<T>> handler) { return future.handle( (value, error) -> { if (error == null) { return CompletableFuture.completedFuture(value); } else if (exceptionClass.isInstance(error.getCause())) { return handler.apply(exceptionClass.cast(error.getCause())); } else if (error instanceof CompletionException) { throw (CompletionException) error; } else { throw new AssertionError(error); } }) .thenCompose(wrapped -> wrapped); } }
CompletableFutures { public static <T, E extends Throwable> CompletableFuture<T> catchingCompose( CompletableFuture<T> future, Class<E> exceptionClass, Function<? super E, ? extends CompletableFuture<T>> handler) { return future.handle( (value, error) -> { if (error == null) { return CompletableFuture.completedFuture(value); } else if (exceptionClass.isInstance(error.getCause())) { return handler.apply(exceptionClass.cast(error.getCause())); } else if (error instanceof CompletionException) { throw (CompletionException) error; } else { throw new AssertionError(error); } }) .thenCompose(wrapped -> wrapped); } private  CompletableFutures(); }
CompletableFutures { public static <T, E extends Throwable> CompletableFuture<T> catchingCompose( CompletableFuture<T> future, Class<E> exceptionClass, Function<? super E, ? extends CompletableFuture<T>> handler) { return future.handle( (value, error) -> { if (error == null) { return CompletableFuture.completedFuture(value); } else if (exceptionClass.isInstance(error.getCause())) { return handler.apply(exceptionClass.cast(error.getCause())); } else if (error instanceof CompletionException) { throw (CompletionException) error; } else { throw new AssertionError(error); } }) .thenCompose(wrapped -> wrapped); } private  CompletableFutures(); static CompletableFuture<List<T>> allAsList(List<CompletableFuture<T>> futures); static CompletableFuture<T> failedFuture(Throwable exception); static CompletableFuture<T> catchingCompose(
      CompletableFuture<T> future,
      Class<E> exceptionClass,
      Function<? super E, ? extends CompletableFuture<T>> handler); }
CompletableFutures { public static <T, E extends Throwable> CompletableFuture<T> catchingCompose( CompletableFuture<T> future, Class<E> exceptionClass, Function<? super E, ? extends CompletableFuture<T>> handler) { return future.handle( (value, error) -> { if (error == null) { return CompletableFuture.completedFuture(value); } else if (exceptionClass.isInstance(error.getCause())) { return handler.apply(exceptionClass.cast(error.getCause())); } else if (error instanceof CompletionException) { throw (CompletionException) error; } else { throw new AssertionError(error); } }) .thenCompose(wrapped -> wrapped); } private  CompletableFutures(); static CompletableFuture<List<T>> allAsList(List<CompletableFuture<T>> futures); static CompletableFuture<T> failedFuture(Throwable exception); static CompletableFuture<T> catchingCompose(
      CompletableFuture<T> future,
      Class<E> exceptionClass,
      Function<? super E, ? extends CompletableFuture<T>> handler);  }