exception - allof - Comportamiento sorprendente de Java 8 CompletableFuture excepcionalmente método
java 8 completionstage (2)
Me he encontrado con el comportamiento extraño de Java 8 CompletableFuture.exceptionally método. Si ejecuto este código, funciona bien e imprime java.lang.RuntimeException
CompletableFuture<String> future = new CompletableFuture<>();
future.completeExceptionally(new RuntimeException());
future.exceptionally(e -> {
System.out.println(e.getClass());
return null;
});
Pero si agrego otro paso en el procesamiento futuro, como thenApply
, thenApply
los cambios de tipo de excepción a java.util.concurrent.CompletionException
con la excepción original thenApply
.
CompletableFuture<String> future = new CompletableFuture<>();
future.completeExceptionally(new RuntimeException());
future.thenApply(v-> v).exceptionally(e -> {
System.out.println(e);
return null;
});
¿Hay alguna razón por la que esto debería estar pasando? En mi opinión, es bastante sorprendente.
Este comportamiento se especifica en la documentación de la clase de CompletionStage
(cuarto punto) :
El
handle
método además permite que la etapa calcule un resultado de reemplazo que puede permitir un procesamiento adicional por parte de otras etapas dependientes. En todos los demás casos, si el cálculo de una etapa finaliza abruptamente con una excepción o error (no verificado), entonces todas las etapas dependientes que requieren su finalización también se completan excepcionalmente, con una excepciónCompletionException
tiene la excepción como su causa.
No es tan sorprendente si considera que puede querer saber si la etapa, la invocó exceptionally
, falló o uno de sus requisitos previos directos o indirectos.
sí, se espera el comportamiento, pero si desea la excepción original que se lanzó desde una de las etapas anteriores, simplemente puede usar esto:
CompletableFuture<String> future = new CompletableFuture<>();
future.completeExceptionally(new RuntimeException());
future.thenApply(v-> v).exceptionally(e -> {
System.out.println(e.getCause()); // returns a throwable back
return null;
});