I have following code:
public final class Start {
private static final CountDownLatch FINAL_THREAD = new CountDownLatch(1);
private static String getValue() {
System.out.println("Waiting...");
try {
Thread.sleep(Duration.ofSeconds(1).toMillis());
return "value";
} catch (InterruptedException e) {
return "interrupted";
}
}
private static void whenComplete(String value, Throwable ex) {
if (ex != null) {
System.out.println("whenComplete Ex: " + ex);
} else {
System.out.println("whenComplete Value: " + value);
}
}
private static String handle(String value, Throwable ex) {
if (ex != null) {
System.out.println("handle Ex: " + ex);
} else {
System.out.println("handle Value: " + value);
}
FINAL_THREAD.countDown();
return value;
}
private static String peek(String value) {
System.out.println("peek: " + value);
return value;
}
private static CompletableFuture<String> createRequest() {
System.out.println("Create....");
return CompletableFuture.supplyAsync(Start::getValue)
.thenApply(Start::peek)
.handle(Start::handle)
.whenComplete(Start::whenComplete);
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
createRequest().completeExceptionally(new RuntimeException("TEST"));
FINAL_THREAD.await();
}
}
When I execute it I get output like this:
> Task :Start.main()
Create....
Waiting...
peek: value
handle Value: value
BUILD SUCCESSFUL in 10s
I don't understand why Start::whenComplete is not called when both Start::peek and Start::handle are. If I switch handle with whenComplete then Start::handle will not be called, but Start::whenComplete will. I would expect that Start::whenComplete will be called with RuntimeExeception in this case, while other stages will be executed with value provided by Start::getValue.