Hi all,

I just stumbled upon a strange behaviour and I'm not sure if it is intended 
this way or whether it's a bug. It is also possible I'm using the API 
incorrectly. Let me explain with an example:

```
var originalException = new Exception("foo");
CompletableFuture.failedFuture(originalException).exceptionally(e -> {
  assert originalException == e;
  return null;
});
```

This works as expected. However the following does not:

```
var originalException = new Exception("foo");
CompletableFuture.failedFuture(originalException).thenCompose(obj -> 
CompletableFuture.completedFuture(obj)).exceptionally(e -> {
  assert originalException == e; // FAIL!
  return null;
});
```

Note, that the "identity"-function passed to `thenCompose(...)` will not even 
be called, since the future is already in failed state. However 
CompletableFuture's implementation wraps the original exception into a new 
CompletionException. So the mere presence of a `thenCompose(...)` somewhere in 
the chain will change how to deal with exceptions further downstream.

Neither do I find this side effect `thenCompose` documented, nor is it part of 
the contract of `exceptionally(...)` or `handle(...)` to only return 
CompletionExceptions. And don't get me started on `get()` and `join()`...

Depending on the context of your code, you don't know whether or not there was 
a `thenCompose`, so you need to check for both, the expected exception as well 
as a CompletionException with its cause being the expected exception.

So is this a bug? Or is this a thing that is not going to be changed, since 
other software already implemented workarounds for this behaviour? If so, 
should I move to 3rd party libs?

Cheers!
Sebastian

Reply via email to