-
Bug
-
Resolution: Fixed
-
P4
-
8, 8u25, 9
-
b48
-
Verified
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8084410 | emb-9 | Doug Lea | P4 | Resolved | Fixed | team |
JDK-8086771 | 8u65 | Doug Lea | P4 | Resolved | Fixed | b01 |
JDK-8069578 | 8u60 | Doug Lea | P4 | Resolved | Fixed | b01 |
JDK-8138201 | emb-8u65 | Unassigned | P4 | Resolved | Fixed | b01 |
JDK-8076724 | emb-8u60 | Doug Lea | P4 | Resolved | Fixed | team |
FULL PRODUCT VERSION :
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Linux 3.13.0-37-generic #64-Ubuntu SMP Mon Sep 22 21:28:38 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
CompletableFuture.thenCompose inconsistently handles exception thrown from the CompletionStage created by function. See the steps to reproduce
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
I have this two tests that only differ in order of execution but produce different output.
@Test
public void completedAfter() {
CompletableFuture<String> future1 = new CompletableFuture<>();
CompletableFuture<String> future2 = new CompletableFuture<>();
future1.thenCompose(x -> future2).whenComplete((r, e) -> System.out.println("After: " + e));
future1.complete("value");
future2.completeExceptionally(new RuntimeException());
}
@Test
public void completedBefore() {
CompletableFuture<String> future1 = new CompletableFuture<>();
CompletableFuture<String> future2 = new CompletableFuture<>();
future1.complete("value");
future2.completeExceptionally(new RuntimeException());
future1.thenCompose(x -> future2).whenComplete((r, e) -> System.out.println("Before: " +e));
}
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Consistent output, most likely:
After: java.util.concurrent.CompletionException: java.lang.RuntimeException
Before: java.util.concurrent.CompletionException: java.lang.RuntimeException
ACTUAL -
Inconsistent output:
After: java.util.concurrent.CompletionException: java.lang.RuntimeException
Before: java.lang.RuntimeException
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import org.junit.Test;
import java.util.concurrent.CompletableFuture;
public class CompletableFutureComposeTest {
@Test
public void completedAfter() {
CompletableFuture<String> future1 = new CompletableFuture<>();
CompletableFuture<String> future2 = new CompletableFuture<>();
future1.thenCompose(x -> future2).whenComplete((r, e) -> System.out.println("After: " + e));
future1.complete("value");
future2.completeExceptionally(new RuntimeException());
}
@Test
public void completedBefore() {
CompletableFuture<String> future1 = new CompletableFuture<>();
CompletableFuture<String> future2 = new CompletableFuture<>();
future1.complete("value");
future2.completeExceptionally(new RuntimeException());
future1.thenCompose(x -> future2).whenComplete((r, e) -> System.out.println("Before: " +e));
}
}
---------- END SOURCE ----------
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Linux 3.13.0-37-generic #64-Ubuntu SMP Mon Sep 22 21:28:38 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
CompletableFuture.thenCompose inconsistently handles exception thrown from the CompletionStage created by function. See the steps to reproduce
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
I have this two tests that only differ in order of execution but produce different output.
@Test
public void completedAfter() {
CompletableFuture<String> future1 = new CompletableFuture<>();
CompletableFuture<String> future2 = new CompletableFuture<>();
future1.thenCompose(x -> future2).whenComplete((r, e) -> System.out.println("After: " + e));
future1.complete("value");
future2.completeExceptionally(new RuntimeException());
}
@Test
public void completedBefore() {
CompletableFuture<String> future1 = new CompletableFuture<>();
CompletableFuture<String> future2 = new CompletableFuture<>();
future1.complete("value");
future2.completeExceptionally(new RuntimeException());
future1.thenCompose(x -> future2).whenComplete((r, e) -> System.out.println("Before: " +e));
}
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Consistent output, most likely:
After: java.util.concurrent.CompletionException: java.lang.RuntimeException
Before: java.util.concurrent.CompletionException: java.lang.RuntimeException
ACTUAL -
Inconsistent output:
After: java.util.concurrent.CompletionException: java.lang.RuntimeException
Before: java.lang.RuntimeException
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import org.junit.Test;
import java.util.concurrent.CompletableFuture;
public class CompletableFutureComposeTest {
@Test
public void completedAfter() {
CompletableFuture<String> future1 = new CompletableFuture<>();
CompletableFuture<String> future2 = new CompletableFuture<>();
future1.thenCompose(x -> future2).whenComplete((r, e) -> System.out.println("After: " + e));
future1.complete("value");
future2.completeExceptionally(new RuntimeException());
}
@Test
public void completedBefore() {
CompletableFuture<String> future1 = new CompletableFuture<>();
CompletableFuture<String> future2 = new CompletableFuture<>();
future1.complete("value");
future2.completeExceptionally(new RuntimeException());
future1.thenCompose(x -> future2).whenComplete((r, e) -> System.out.println("Before: " +e));
}
}
---------- END SOURCE ----------
- backported by
-
JDK-8069578 Inconsistent exception handling in CompletableFuture.thenCompose
-
- Resolved
-
-
JDK-8076724 Inconsistent exception handling in CompletableFuture.thenCompose
-
- Resolved
-
-
JDK-8084410 Inconsistent exception handling in CompletableFuture.thenCompose
-
- Resolved
-
-
JDK-8086771 Inconsistent exception handling in CompletableFuture.thenCompose
-
- Resolved
-
-
JDK-8138201 Inconsistent exception handling in CompletableFuture.thenCompose
-
- Resolved
-