Skip to Main Content

Java APIs

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Interested in getting your voice heard by members of the Developer Marketing team at Oracle? Check out this post for AppDev or this post for AI focus group information.

Exception handling proposals in CompletionStage/CompletableFuture

Joris GuffensJan 12 2024 — edited Jan 12 2024

I've struggled with this a few times in the past years. There are much more methods for normal completion as opposed to exceptional completion in the CompletionStage interface.

I just want to handle an exceptional completion from a previous stage in the chain. For a problem that should be trivial, the options are:

doSomethingAsync()
    .thenAccept(result -> handleResult(result))
    
    // option 1
    .exceptionally(throwable -> {
        LOGGER.error(throwable);
        return null; 
    })
    
    // option 2
    .whenComplete((result, throwable) -> {
        if ( throwable != null ) {
            LOGGER.error(throwable);
        }
    })
    
    // option 3
    .handle((result, throwable) -> {
        if ( throwable != null ) {
            LOGGER.error(throwable);
        }
        return null;
    })

For reference of these methods: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/concurrent/CompletionStage.html

Option 1
I have to return a value for the new stage to complete normally. What if I don't have a meaningful fallback value or I don't want to continue completing normally?

Option 2
I have to check if the stage completed exceptionally. In this case, this is too verbose for something that should be trivial. I also don't have any use for the result parameter.

Option 3
Has both the issues of option 1 and option 2.

Additionally, I have seen some smelly things happen which could have been avoided with a better API. For example when the last stage of the chain is:

.whenComplete((result, throwable) -> {
    if ( throwable != null ) {
        LOGGER.error(throwable);
    }
    handleResult(result); // <- what if an exception occurs here? This will not be handled.
})

Proposed solutions
Just as with .thenApply(…) and .thenAccept(…) I think that .exceptionally(…) should respectively have been .exceptionallyApply(…) and .exceptionallyAccept(…). Continuing normal completion without a value is a valid use case.

But then again, what if you don't want to continue normal completion? There might be future stages that expect a non-null value and you can't provide a meaningful fallback, you want to continue the exceptional flow. That's why I also suggest .whenExceptionally(…) which behaves the same as .whenComplete(…) but accepts a Consumer with only the throwable parameter. (It might also be nice to add a similar method for normal completion)

Please let me know what you think!

Comments

Hiroshi Tonegawa May 31 2024

追加情報です。

リスナーからエラーメッセージでておりました。ただどうしたら良いのかわかりません。

そのlog(TNSLSNR.log)を添付しました。ここから原因、また対処法など解析できませんでしょうか?

大変困っております。よろしくお願いいたします。

TNSLSNR_496.log

1 - 1

Post Details

Added on Jan 12 2024
1 comment
567 views