Skip to content

CompletionStage.await shall unwrap CompletionException #375

Closed
@elizarov

Description

@elizarov

See discussion here: https://youtrack.jetbrains.com/issue/KT-24481

The following code clearly demonstrates the problem:

import java.util.concurrent.*

fun see(f: CompletableFuture<*>, s: String) {
    f.whenComplete { res, err ->
        val getRes =
            try { f.get().toString() }
            catch (e: Throwable) { e.toString() }
        println("$s: Completed" +
            "\n\twhenComplete result = $res" +
            "\n\twhenComplete  error = $err" +
            "\n\t       get() result = $getRes")
    }
}

fun main(args: Array<String>) {
    class DomainSpecificException : RuntimeException()

    val cf1 = CompletableFuture<Int>()
    val cf2 = CompletableFuture<Int>()
    val cf3 = cf1.thenCompose { cf2 }

    see(cf1,"cf1")
    see(cf2,"cf2")
    see(cf3,"cf3")

    cf2.completeExceptionally(DomainSpecificException())
    cf1.complete(239)
}

The result is:

cf2: Completed
	whenComplete result = null
	whenComplete  error = KT24481Kt$main$DomainSpecificException
	       get() result = java.util.concurrent.ExecutionException: KT24481Kt$main$DomainSpecificException
cf1: Completed
	whenComplete result = 239
	whenComplete  error = null
	       get() result = 239
cf3: Completed
	whenComplete result = null
	whenComplete  error = java.util.concurrent.CompletionException: KT24481Kt$main$DomainSpecificException
	       get() result = java.util.concurrent.ExecutionException: KT24481Kt$main$DomainSpecificException

You can clearly see that CompletableFuture.get() not just simply wraps the resulting exception into ExecutionException, but it also unwraps CompletionException before doing so. This behavior can be confirmed from its source, too. This CompletionException unwrapping behavior shall be replicated by CompletionStage.await() slow path, too.

The goal is that CompletionStage.await() shall throw unwrapped DomainSpecificException for both cf2 and cf3 in the above example.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions