IgniteFutureImpl implements IgniteFuture<V> { @Override public <T> IgniteFuture<T> chain(final IgniteClosure<? super IgniteFuture<V>, T> doneCb) { return new IgniteFutureImpl<>(chainInternal(doneCb, null)); } IgniteFutureImpl(IgniteInternalFuture<V> fut); IgniteInternalFuture<V> internalFuture(); @Override boolean isCancelled(); @Override boolean isDone(); @Override void listen(IgniteInClosure<? super IgniteFuture<V>> lsnr); @Override void listenAsync(IgniteInClosure<? super IgniteFuture<V>> lsnr, Executor exec); @Override IgniteFuture<T> chain(final IgniteClosure<? super IgniteFuture<V>, T> doneCb); @Override IgniteFuture<T> chainAsync(final IgniteClosure<? super IgniteFuture<V>, T> doneCb,
        Executor exec); @Override boolean cancel(); @Override V get(); @Override V get(long timeout); @Override V get(long timeout, TimeUnit unit); @Override String toString();  }
@Test public void testChain() throws Exception { GridFutureAdapter<String> fut0 = new GridFutureAdapter<>(); IgniteFutureImpl<String> fut = createFuture(fut0); IgniteFuture<Integer> chained = fut.chain(new C1<IgniteFuture<String>, Integer>() { @Override public Integer apply(IgniteFuture<String> fut) { return Integer.valueOf(fut.get()); } }); assertFalse(chained.isDone()); U.sleep(100); final AtomicInteger lsnrCnt = new AtomicInteger(); chained.listen(new CI1<IgniteFuture<Integer>>() { @Override public void apply(IgniteFuture<Integer> fut) { assertEquals(10, (int)fut.get()); lsnrCnt.incrementAndGet(); } }); fut0.onDone("10"); assertTrue(chained.isDone()); assertEquals(10, (int)chained.get()); assertEquals(1, lsnrCnt.get()); assertTrue(fut.isDone()); assertEquals("10", fut.get()); }