completionstage completablefuture allof exception java-8 future

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ón CompletionException 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; });