// debuging: Intellij issue to see variable:
 // http://stackoverflow.com/questions/26895708/debugger-cannot-see-local-variable-in-a-lambda
 ///  vs anon class: variable visible. new instances??
 // stack traces: we see "lambda" as method name. maybe meth reference? but closures are not
 // possible ...
 ////////////////// read further:
 // http://baddotrobot.com/blog/2014/02/18/method-references-in-java8/
 @GET
 public void findById(@QueryParam("id") int id, @Suspended AsyncResponse asyncResponse) {
   asyncResponse.setTimeout(10, TimeUnit.SECONDS);
   final CompletableFuture<Product> product = productDao.findNameById(id);
   final CompletableFuture<ProductWithGroups> finalResult =
       product.thenCompose(
           productFound -> {
             if (asyncResponse.isDone()) {
               final CompletableFuture<ProductWithGroups> error = new CompletableFuture<>();
               error.completeExceptionally(new IllegalStateException("Response already done"));
               return error;
             } else {
               final CompletableFuture<List<ProductGroup>> productGroups =
                   productDao.findProductGroupsById(id);
               return productGroups.thenApply(
                   productGroupsFound ->
                       ProductWithGroups.createProductWithGroups(
                           productFound, productGroupsFound));
             }
           });
   finalResult.whenCompleteAsync(
       (productWithGroups, error) -> {
         consumeProductWithGroupOrError(asyncResponse, productWithGroups, error);
       },
       executorToCompleteCalls);
 }
  @Override
  public CompletableFuture<Void> transactionDataFuture(int expectedTopologyId) {
    if (transactionDataTopologyId >= expectedTopologyId) return CompletableFutures.completedNull();

    if (trace) {
      log.tracef(
          "Waiting for transaction data for topology %d, current topology is %d",
          expectedTopologyId, transactionDataTopologyId);
    }
    synchronized (this) {
      if (transactionDataTopologyId >= expectedTopologyId) {
        return CompletableFutures.completedNull();
      } else {
        return transactionDataFuture.thenCompose(nil -> transactionDataFuture(expectedTopologyId));
      }
    }
  }
  public static void main(String[] args) throws Exception {
    CreateFunctionalMaps.main(args);
    FunctionalMap.ReadOnlyMap<String, String> readOnlyMap = CreateFunctionalMaps.ro;
    FunctionalMap.WriteOnlyMap<String, String> writeOnlyMap = CreateFunctionalMaps.wo;
    FunctionalMap.ReadWriteMap<String, String> readWriteMap = CreateFunctionalMaps.rw;

    CompletableFuture<Void> f0 =
        writeOnlyMap.eval(
            "key",
            "value1",
            (v, writeView) ->
                writeView.set(
                    v, new MetaParam.MetaEntryVersion<>(new EntryVersion.NumericEntryVersion(1))));
    CompletableFuture<Boolean> f1 =
        f0.thenCompose(
            x ->
                readWriteMap.eval(
                    "key",
                    "value2",
                    (v, readWriteView) -> {
                      // .class does not give generics, so use a helper type() method
                      Class<MetaParam.MetaEntryVersion<Long>> clazz =
                          MetaParam.MetaEntryVersion.type();
                      Optional<MetaParam.MetaEntryVersion<Long>> metaParam =
                          readWriteView.findMetaParam(clazz);
                      return metaParam
                          .map(
                              metaVersion -> {
                                if (metaVersion
                                        .get()
                                        .compareTo(new EntryVersion.NumericEntryVersion(1))
                                    == EQUAL) {
                                  readWriteView.set(
                                      "uno",
                                      new MetaParam.MetaEntryVersion<>(
                                          new EntryVersion.NumericEntryVersion(200)));
                                  return true; // version matches
                                }
                                return false; // version does not match
                              })
                          .orElse(false); // version not present
                    }));

    System.out.println(f1.get());
  }
Beispiel #4
0
  private static void test(ExecutorService executor) throws Throwable {

    Thread.currentThread().setName("mainThread");

    // ----------------------------------------------------------------
    // supplyAsync tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<String> cf = supplyAsync(() -> "a test string");
      checkCompletedNormally(cf, cf.join());
      cf = supplyAsync(() -> "a test string", commonPool());
      checkCompletedNormally(cf, cf.join());
      cf = supplyAsync(() -> "a test string", executor);
      checkCompletedNormally(cf, cf.join());
      cf =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      checkCompletedExceptionally(cf);
      cf =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              },
              commonPool());
      checkCompletedExceptionally(cf);
      cf =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              },
              executor);
      checkCompletedExceptionally(cf);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // runAsync tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Void> cf = runAsync(() -> {});
      checkCompletedNormally(cf, cf.join());
      cf = runAsync(() -> {}, commonPool());
      checkCompletedNormally(cf, cf.join());
      cf = runAsync(() -> {}, executor);
      checkCompletedNormally(cf, cf.join());
      cf =
          runAsync(
              () -> {
                throw new RuntimeException();
              });
      checkCompletedExceptionally(cf);
      cf =
          runAsync(
              () -> {
                throw new RuntimeException();
              },
              commonPool());
      checkCompletedExceptionally(cf);
      cf =
          runAsync(
              () -> {
                throw new RuntimeException();
              },
              executor);
      checkCompletedExceptionally(cf);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // explicit completion
    // ----------------------------------------------------------------
    try {
      final Phaser phaser = new Phaser(1);
      final int phase = phaser.getPhase();
      CompletableFuture<Integer> cf;
      cf =
          supplyAsync(
              () -> {
                phaser.awaitAdvance(phase);
                return 1;
              });
      cf.complete(2);
      phaser.arrive();
      checkCompletedNormally(cf, 2);

      cf =
          supplyAsync(
              () -> {
                phaser.awaitAdvance(phase + 1);
                return 1;
              });
      cf.completeExceptionally(new Throwable());
      phaser.arrive();
      checkCompletedExceptionally(cf);

      cf =
          supplyAsync(
              () -> {
                phaser.awaitAdvance(phase + 2);
                return 1;
              });
      cf.cancel(true);
      phaser.arrive();
      checkCompletedExceptionally(cf, true);

      cf =
          supplyAsync(
              () -> {
                phaser.awaitAdvance(phase + 3);
                return 1;
              });
      check(cf.getNow(2) == 2);
      phaser.arrive();
      checkCompletedNormally(cf, 1);
      check(cf.getNow(2) == 1);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // thenApplyXXX tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Integer> cf2;
      CompletableFuture<String> cf1 = supplyAsync(() -> "a test string");
      cf2 =
          cf1.thenApply(
              (x) -> {
                if (x.equals("a test string")) return 1;
                else return 0;
              });
      checkCompletedNormally(cf1, "a test string");
      checkCompletedNormally(cf2, 1);

      cf1 = supplyAsync(() -> "a test string");
      cf2 =
          cf1.thenApplyAsync(
              (x) -> {
                if (x.equals("a test string")) return 1;
                else return 0;
              });
      checkCompletedNormally(cf1, "a test string");
      checkCompletedNormally(cf2, 1);

      cf1 = supplyAsync(() -> "a test string");
      cf2 =
          cf1.thenApplyAsync(
              (x) -> {
                if (x.equals("a test string")) return 1;
                else return 0;
              },
              executor);
      checkCompletedNormally(cf1, "a test string");
      checkCompletedNormally(cf2, 1);

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          cf1.thenApply(
              (x) -> {
                return 0;
              });
      checkCompletedExceptionally(cf1);
      checkCompletedExceptionally(cf2);

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          cf1.thenApplyAsync(
              (x) -> {
                return 0;
              });
      checkCompletedExceptionally(cf1);
      checkCompletedExceptionally(cf2);

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          cf1.thenApplyAsync(
              (x) -> {
                return 0;
              },
              executor);
      checkCompletedExceptionally(cf1);
      checkCompletedExceptionally(cf2);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // thenAcceptXXX tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Void> cf2;
      int before = atomicInt.get();
      CompletableFuture<String> cf1 = supplyAsync(() -> "a test string");
      cf2 =
          cf1.thenAccept(
              (x) -> {
                if (x.equals("a test string")) {
                  atomicInt.incrementAndGet();
                  return;
                }
                throw new RuntimeException();
              });
      checkCompletedNormally(cf1, "a test string");
      checkCompletedNormally(cf2, null);
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 = supplyAsync(() -> "a test string");
      cf2 =
          cf1.thenAcceptAsync(
              (x) -> {
                if (x.equals("a test string")) {
                  atomicInt.incrementAndGet();
                  return;
                }
                throw new RuntimeException();
              });
      checkCompletedNormally(cf1, "a test string");
      checkCompletedNormally(cf2, null);
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 = supplyAsync(() -> "a test string");
      cf2 =
          cf1.thenAcceptAsync(
              (x) -> {
                if (x.equals("a test string")) {
                  atomicInt.incrementAndGet();
                  return;
                }
                throw new RuntimeException();
              },
              executor);
      checkCompletedNormally(cf1, "a test string");
      checkCompletedNormally(cf2, null);
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          cf1.thenAccept(
              (x) -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedExceptionally(cf1);
      checkCompletedExceptionally(cf2);
      check(atomicInt.get() == before);

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          cf1.thenAcceptAsync(
              (x) -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedExceptionally(cf1);
      checkCompletedExceptionally(cf2);
      check(atomicInt.get() == before);

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          cf1.thenAcceptAsync(
              (x) -> {
                atomicInt.incrementAndGet();
              },
              executor);
      checkCompletedExceptionally(cf1);
      checkCompletedExceptionally(cf2);
      check(atomicInt.get() == before);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // thenRunXXX tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Void> cf2;
      int before = atomicInt.get();
      CompletableFuture<String> cf1 = supplyAsync(() -> "a test string");
      cf2 =
          cf1.thenRun(
              () -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cf1, "a test string");
      checkCompletedNormally(cf2, null);
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 = supplyAsync(() -> "a test string");
      cf2 =
          cf1.thenRunAsync(
              () -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cf1, "a test string");
      checkCompletedNormally(cf2, null);
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 = supplyAsync(() -> "a test string");
      cf2 =
          cf1.thenRunAsync(
              () -> {
                atomicInt.incrementAndGet();
              },
              executor);
      checkCompletedNormally(cf1, "a test string");
      checkCompletedNormally(cf2, null);
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          cf1.thenRun(
              () -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedExceptionally(cf1);
      checkCompletedExceptionally(cf2);
      check(atomicInt.get() == before);

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          cf1.thenRunAsync(
              () -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedExceptionally(cf1);
      checkCompletedExceptionally(cf2);
      check(atomicInt.get() == before);

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          cf1.thenRunAsync(
              () -> {
                atomicInt.incrementAndGet();
              },
              executor);
      checkCompletedExceptionally(cf1);
      checkCompletedExceptionally(cf2);
      check(atomicInt.get() == before);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // thenCombineXXX tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Integer> cf3;
      CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
      CompletableFuture<Integer> cf2 = supplyAsync(() -> 1);
      cf3 =
          cf1.thenCombine(
              cf2,
              (x, y) -> {
                return x + y;
              });
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf2, 1);
      checkCompletedNormally(cf3, 2);

      cf1 = supplyAsync(() -> 1);
      cf2 = supplyAsync(() -> 1);
      cf3 =
          cf1.thenCombineAsync(
              cf2,
              (x, y) -> {
                return x + y;
              });
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf2, 1);
      checkCompletedNormally(cf3, 2);

      cf1 = supplyAsync(() -> 1);
      cf2 = supplyAsync(() -> 1);
      cf3 =
          cf1.thenCombineAsync(
              cf2,
              (x, y) -> {
                return x + y;
              },
              executor);
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf2, 1);
      checkCompletedNormally(cf3, 2);

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 = supplyAsync(() -> 1);
      cf3 =
          cf1.thenCombine(
              cf2,
              (x, y) -> {
                return 0;
              });
      checkCompletedExceptionally(cf1);
      checkCompletedNormally(cf2, 1);
      checkCompletedExceptionally(cf3);

      cf1 = supplyAsync(() -> 1);
      cf2 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf3 =
          cf1.thenCombineAsync(
              cf2,
              (x, y) -> {
                return 0;
              });
      checkCompletedNormally(cf1, 1);
      checkCompletedExceptionally(cf2);
      checkCompletedExceptionally(cf3);

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf3 =
          cf1.thenCombineAsync(
              cf2,
              (x, y) -> {
                return 0;
              },
              executor);
      checkCompletedExceptionally(cf1);
      checkCompletedExceptionally(cf2);
      checkCompletedExceptionally(cf3);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // thenAcceptBothXXX tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Void> cf3;
      int before = atomicInt.get();
      CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
      CompletableFuture<Integer> cf2 = supplyAsync(() -> 1);
      cf3 =
          cf1.thenAcceptBoth(
              cf2,
              (x, y) -> {
                check(x + y == 2);
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf2, 1);
      checkCompletedNormally(cf3, null);
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 = supplyAsync(() -> 1);
      cf2 = supplyAsync(() -> 1);
      cf3 =
          cf1.thenAcceptBothAsync(
              cf2,
              (x, y) -> {
                check(x + y == 2);
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf2, 1);
      checkCompletedNormally(cf3, null);
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 = supplyAsync(() -> 1);
      cf2 = supplyAsync(() -> 1);
      cf3 =
          cf1.thenAcceptBothAsync(
              cf2,
              (x, y) -> {
                check(x + y == 2);
                atomicInt.incrementAndGet();
              },
              executor);
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf2, 1);
      checkCompletedNormally(cf3, null);
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 = supplyAsync(() -> 1);
      cf3 =
          cf1.thenAcceptBoth(
              cf2,
              (x, y) -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedExceptionally(cf1);
      checkCompletedNormally(cf2, 1);
      checkCompletedExceptionally(cf3);
      check(atomicInt.get() == before);

      cf1 = supplyAsync(() -> 1);
      cf2 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf3 =
          cf1.thenAcceptBothAsync(
              cf2,
              (x, y) -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cf1, 1);
      checkCompletedExceptionally(cf2);
      checkCompletedExceptionally(cf3);
      check(atomicInt.get() == before);

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf3 =
          cf1.thenAcceptBothAsync(
              cf2,
              (x, y) -> {
                atomicInt.incrementAndGet();
              },
              executor);
      checkCompletedExceptionally(cf1);
      checkCompletedExceptionally(cf2);
      checkCompletedExceptionally(cf3);
      check(atomicInt.get() == before);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // runAfterBothXXX tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Void> cf3;
      int before = atomicInt.get();
      CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
      CompletableFuture<Integer> cf2 = supplyAsync(() -> 1);
      cf3 =
          cf1.runAfterBoth(
              cf2,
              () -> {
                check(cf1.isDone());
                check(cf2.isDone());
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf2, 1);
      checkCompletedNormally(cf3, null);
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      CompletableFuture<Integer> cfa = supplyAsync(() -> 1);
      CompletableFuture<Integer> cfb = supplyAsync(() -> 1);
      cf3 =
          cfa.runAfterBothAsync(
              cfb,
              () -> {
                check(cfa.isDone());
                check(cfb.isDone());
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cfa, 1);
      checkCompletedNormally(cfb, 1);
      checkCompletedNormally(cf3, null);
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      CompletableFuture<Integer> cfx = supplyAsync(() -> 1);
      CompletableFuture<Integer> cfy = supplyAsync(() -> 1);
      cf3 =
          cfy.runAfterBothAsync(
              cfx,
              () -> {
                check(cfx.isDone());
                check(cfy.isDone());
                atomicInt.incrementAndGet();
              },
              executor);
      checkCompletedNormally(cfx, 1);
      checkCompletedNormally(cfy, 1);
      checkCompletedNormally(cf3, null);
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      CompletableFuture<Integer> cf4 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      CompletableFuture<Integer> cf5 = supplyAsync(() -> 1);
      cf3 =
          cf5.runAfterBothAsync(
              cf4,
              () -> {
                atomicInt.incrementAndGet();
              },
              executor);
      checkCompletedExceptionally(cf4);
      checkCompletedNormally(cf5, 1);
      checkCompletedExceptionally(cf3);
      check(atomicInt.get() == before);

      before = atomicInt.get();
      cf4 = supplyAsync(() -> 1);
      cf5 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf3 =
          cf5.runAfterBothAsync(
              cf4,
              () -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cf4, 1);
      checkCompletedExceptionally(cf5);
      checkCompletedExceptionally(cf3);
      check(atomicInt.get() == before);

      before = atomicInt.get();
      cf4 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf5 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf3 =
          cf5.runAfterBoth(
              cf4,
              () -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedExceptionally(cf4);
      checkCompletedExceptionally(cf5);
      checkCompletedExceptionally(cf3);
      check(atomicInt.get() == before);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // applyToEitherXXX tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Integer> cf3;
      CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
      CompletableFuture<Integer> cf2 = supplyAsync(() -> 2);
      cf3 =
          cf1.applyToEither(
              cf2,
              (x) -> {
                check(x == 1 || x == 2);
                return x;
              });
      checkCompletedNormally(cf3, new Object[] {1, 2});
      check(cf1.isDone() || cf2.isDone());

      cf1 = supplyAsync(() -> 1);
      cf2 = supplyAsync(() -> 2);
      cf3 =
          cf1.applyToEitherAsync(
              cf2,
              (x) -> {
                check(x == 1 || x == 2);
                return x;
              });
      checkCompletedNormally(cf3, new Object[] {1, 2});
      check(cf1.isDone() || cf2.isDone());

      cf1 = supplyAsync(() -> 1);
      cf2 = supplyAsync(() -> 2);
      cf3 =
          cf1.applyToEitherAsync(
              cf2,
              (x) -> {
                check(x == 1 || x == 2);
                return x;
              },
              executor);
      checkCompletedNormally(cf3, new Object[] {1, 2});
      check(cf1.isDone() || cf2.isDone());

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 = supplyAsync(() -> 2);
      cf3 =
          cf1.applyToEither(
              cf2,
              (x) -> {
                check(x == 2);
                return x;
              });
      try {
        check(cf3.join() == 2);
      } catch (CompletionException x) {
        pass();
      }
      check(cf3.isDone());
      check(cf1.isDone() || cf2.isDone());

      cf1 = supplyAsync(() -> 1);
      cf2 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf3 =
          cf1.applyToEitherAsync(
              cf2,
              (x) -> {
                check(x == 1);
                return x;
              });
      try {
        check(cf3.join() == 1);
      } catch (CompletionException x) {
        pass();
      }
      check(cf3.isDone());
      check(cf1.isDone() || cf2.isDone());

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf3 =
          cf1.applyToEitherAsync(
              cf2,
              (x) -> {
                fail();
                return x;
              });
      checkCompletedExceptionally(cf3);
      check(cf1.isDone() || cf2.isDone());

      final Phaser cf3Done = new Phaser(2);
      cf1 =
          supplyAsync(
              () -> {
                cf3Done.arriveAndAwaitAdvance();
                return 1;
              });
      cf2 = supplyAsync(() -> 2);
      cf3 =
          cf1.applyToEither(
              cf2,
              (x) -> {
                check(x == 2);
                return x;
              });
      checkCompletedNormally(cf3, 2);
      checkCompletedNormally(cf2, 2);
      check(!cf1.isDone());
      cf3Done.arrive();
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf3, 2);

      cf1 = supplyAsync(() -> 1);
      cf2 =
          supplyAsync(
              () -> {
                cf3Done.arriveAndAwaitAdvance();
                return 2;
              });
      cf3 =
          cf1.applyToEitherAsync(
              cf2,
              (x) -> {
                check(x == 1);
                return x;
              });
      checkCompletedNormally(cf3, 1);
      checkCompletedNormally(cf1, 1);
      check(!cf2.isDone());
      cf3Done.arrive();
      checkCompletedNormally(cf2, 2);
      checkCompletedNormally(cf3, 1);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // acceptEitherXXX tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Void> cf3;
      int before = atomicInt.get();
      CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
      CompletableFuture<Integer> cf2 = supplyAsync(() -> 2);
      cf3 =
          cf1.acceptEither(
              cf2,
              (x) -> {
                check(x == 1 || x == 2);
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cf3, null);
      check(cf1.isDone() || cf2.isDone());
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 = supplyAsync(() -> 1);
      cf2 = supplyAsync(() -> 2);
      cf3 =
          cf1.acceptEitherAsync(
              cf2,
              (x) -> {
                check(x == 1 || x == 2);
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cf3, null);
      check(cf1.isDone() || cf2.isDone());
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 = supplyAsync(() -> 1);
      cf2 = supplyAsync(() -> 2);
      cf3 =
          cf2.acceptEitherAsync(
              cf1,
              (x) -> {
                check(x == 1 || x == 2);
                atomicInt.incrementAndGet();
              },
              executor);
      checkCompletedNormally(cf3, null);
      check(cf1.isDone() || cf2.isDone());
      check(atomicInt.get() == (before + 1));

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 = supplyAsync(() -> 2);
      cf3 =
          cf2.acceptEitherAsync(
              cf1,
              (x) -> {
                check(x == 2);
              },
              executor);
      try {
        check(cf3.join() == null);
      } catch (CompletionException x) {
        pass();
      }
      check(cf3.isDone());
      check(cf1.isDone() || cf2.isDone());

      cf1 = supplyAsync(() -> 1);
      cf2 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf3 =
          cf2.acceptEitherAsync(
              cf1,
              (x) -> {
                check(x == 1);
              });
      try {
        check(cf3.join() == null);
      } catch (CompletionException x) {
        pass();
      }
      check(cf3.isDone());
      check(cf1.isDone() || cf2.isDone());

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf3 =
          cf2.acceptEitherAsync(
              cf1,
              (x) -> {
                fail();
              });
      checkCompletedExceptionally(cf3);
      check(cf1.isDone() || cf2.isDone());

      final Phaser cf3Done = new Phaser(2);
      cf1 =
          supplyAsync(
              () -> {
                cf3Done.arriveAndAwaitAdvance();
                return 1;
              });
      cf2 = supplyAsync(() -> 2);
      cf3 =
          cf1.acceptEither(
              cf2,
              (x) -> {
                check(x == 2);
              });
      checkCompletedNormally(cf3, null);
      checkCompletedNormally(cf2, 2);
      check(!cf1.isDone());
      cf3Done.arrive();
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf3, null);

      cf1 = supplyAsync(() -> 1);
      cf2 =
          supplyAsync(
              () -> {
                cf3Done.arriveAndAwaitAdvance();
                return 2;
              });
      cf3 =
          cf1.acceptEitherAsync(
              cf2,
              (x) -> {
                check(x == 1);
              });
      checkCompletedNormally(cf3, null);
      checkCompletedNormally(cf1, 1);
      check(!cf2.isDone());
      cf3Done.arrive();
      checkCompletedNormally(cf2, 2);
      checkCompletedNormally(cf3, null);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // runAfterEitherXXX tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Void> cf3;
      int before = atomicInt.get();
      CompletableFuture<Void> cf1 = runAsync(() -> {});
      CompletableFuture<Void> cf2 = runAsync(() -> {});
      cf3 =
          cf1.runAfterEither(
              cf2,
              () -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cf3, null);
      check(cf1.isDone() || cf2.isDone());
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 = runAsync(() -> {});
      cf2 = runAsync(() -> {});
      cf3 =
          cf1.runAfterEitherAsync(
              cf2,
              () -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cf3, null);
      check(cf1.isDone() || cf2.isDone());
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 = runAsync(() -> {});
      cf2 = runAsync(() -> {});
      cf3 =
          cf2.runAfterEitherAsync(
              cf1,
              () -> {
                atomicInt.incrementAndGet();
              },
              executor);
      checkCompletedNormally(cf3, null);
      check(cf1.isDone() || cf2.isDone());
      check(atomicInt.get() == (before + 1));

      before = atomicInt.get();
      cf1 =
          runAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 = runAsync(() -> {});
      cf3 =
          cf2.runAfterEither(
              cf1,
              () -> {
                atomicInt.incrementAndGet();
              });
      try {
        check(cf3.join() == null);
        check(atomicInt.get() == (before + 1));
      } catch (CompletionException x) {
        pass();
      }
      check(cf3.isDone());
      check(cf1.isDone() || cf2.isDone());

      before = atomicInt.get();
      cf1 = runAsync(() -> {});
      cf2 =
          runAsync(
              () -> {
                throw new RuntimeException();
              });
      cf3 =
          cf1.runAfterEitherAsync(
              cf2,
              () -> {
                atomicInt.incrementAndGet();
              });
      try {
        check(cf3.join() == null);
        check(atomicInt.get() == (before + 1));
      } catch (CompletionException x) {
        pass();
      }
      check(cf3.isDone());
      check(cf1.isDone() || cf2.isDone());

      before = atomicInt.get();
      cf1 =
          runAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          runAsync(
              () -> {
                throw new RuntimeException();
              });
      cf3 =
          cf2.runAfterEitherAsync(
              cf1,
              () -> {
                atomicInt.incrementAndGet();
              },
              executor);
      checkCompletedExceptionally(cf3);
      check(cf1.isDone() || cf2.isDone());
      check(atomicInt.get() == before);

      final Phaser cf3Done = new Phaser(2);
      before = atomicInt.get();
      cf1 =
          runAsync(
              () -> {
                cf3Done.arriveAndAwaitAdvance();
              });
      cf2 = runAsync(() -> {});
      cf3 =
          cf1.runAfterEither(
              cf2,
              () -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cf3, null);
      checkCompletedNormally(cf2, null);
      check(!cf1.isDone());
      check(atomicInt.get() == (before + 1));
      cf3Done.arrive();
      checkCompletedNormally(cf1, null);
      checkCompletedNormally(cf3, null);

      before = atomicInt.get();
      cf1 = runAsync(() -> {});
      cf2 =
          runAsync(
              () -> {
                cf3Done.arriveAndAwaitAdvance();
              });
      cf3 =
          cf1.runAfterEitherAsync(
              cf2,
              () -> {
                atomicInt.incrementAndGet();
              });
      checkCompletedNormally(cf3, null);
      checkCompletedNormally(cf1, null);
      check(!cf2.isDone());
      check(atomicInt.get() == (before + 1));
      cf3Done.arrive();
      checkCompletedNormally(cf2, null);
      checkCompletedNormally(cf3, null);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // thenComposeXXX tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Integer> cf2;
      CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
      cf2 =
          cf1.thenCompose(
              (x) -> {
                check(x == 1);
                return CompletableFuture.completedFuture(2);
              });
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf2, 2);

      cf1 = supplyAsync(() -> 1);
      cf2 =
          cf1.thenComposeAsync(
              (x) -> {
                check(x == 1);
                return CompletableFuture.completedFuture(2);
              });
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf2, 2);

      cf1 = supplyAsync(() -> 1);
      cf2 =
          cf1.thenComposeAsync(
              (x) -> {
                check(x == 1);
                return CompletableFuture.completedFuture(2);
              },
              executor);
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf2, 2);

      int before = atomicInt.get();
      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          cf1.thenCompose(
              (x) -> {
                atomicInt.incrementAndGet();
                return CompletableFuture.completedFuture(2);
              });
      checkCompletedExceptionally(cf1);
      checkCompletedExceptionally(cf2);
      check(atomicInt.get() == before);

      cf1 =
          supplyAsync(
              () -> {
                throw new RuntimeException();
              });
      cf2 =
          cf1.thenComposeAsync(
              (x) -> {
                atomicInt.incrementAndGet();
                return CompletableFuture.completedFuture(2);
              });
      checkCompletedExceptionally(cf1);
      checkCompletedExceptionally(cf2);
      check(atomicInt.get() == before);

      cf1 = supplyAsync(() -> 1);
      cf2 =
          cf1.thenComposeAsync(
              (x) -> {
                throw new RuntimeException();
              },
              executor);
      checkCompletedNormally(cf1, 1);
      checkCompletedExceptionally(cf2);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // anyOf tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Object> cf3;
      for (int k = 0; k < 10; k++) {
        CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
        CompletableFuture<Integer> cf2 = supplyAsync(() -> 2);
        cf3 = CompletableFuture.anyOf(cf1, cf2);
        checkCompletedNormally(cf3, new Object[] {1, 2});
        check(cf1.isDone() || cf2.isDone());
      }
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // allOf tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<?> cf3;
      for (int k = 0; k < 10; k++) {
        CompletableFuture<Integer>[] cfs =
            (CompletableFuture<Integer>[]) Array.newInstance(CompletableFuture.class, 10);
        for (int j = 0; j < 10; j++) {
          final int v = j;
          cfs[j] = supplyAsync(() -> v);
        }
        cf3 = CompletableFuture.allOf(cfs);
        for (int j = 0; j < 10; j++) checkCompletedNormally(cfs[j], j);
        checkCompletedNormally(cf3, null);
      }
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // exceptionally tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Integer> cf2;
      CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
      cf2 =
          cf1.exceptionally(
              (t) -> {
                fail("function should never be called");
                return 2;
              });
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf2, 1);

      final RuntimeException t = new RuntimeException();
      cf1 =
          supplyAsync(
              () -> {
                throw t;
              });
      cf2 =
          cf1.exceptionally(
              (x) -> {
                check(x.getCause() == t);
                return 2;
              });
      checkCompletedExceptionally(cf1);
      checkCompletedNormally(cf2, 2);
    } catch (Throwable t) {
      unexpected(t);
    }

    // ----------------------------------------------------------------
    // handle tests
    // ----------------------------------------------------------------
    try {
      CompletableFuture<Integer> cf2;
      CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
      cf2 = cf1.handle((x, t) -> x + 1);
      checkCompletedNormally(cf1, 1);
      checkCompletedNormally(cf2, 2);

      final RuntimeException ex = new RuntimeException();
      cf1 =
          supplyAsync(
              () -> {
                throw ex;
              });
      cf2 =
          cf1.handle(
              (x, t) -> {
                check(t.getCause() == ex);
                return 2;
              });
      checkCompletedExceptionally(cf1);
      checkCompletedNormally(cf2, 2);
    } catch (Throwable t) {
      unexpected(t);
    }
  }
Beispiel #5
0
 /**
  * Returns videos by user. Shows example of the composing two subsequent asynchronous operations:
  * at first, the user is retrieved, then his videos are retrieved.
  *
  * @param userFuture Completable future of the user.
  * @return User future.
  */
 public CompletableFuture<List<Video>> getByOwner(CompletableFuture<User> userFuture) {
   return userFuture.thenCompose(this::getByOwner);
 }