How to catch exceptions within Java 8 Stream.flatMap(..) - java

Given a Stream and a method that returns a Stream for different arguments as data source, I'm looking for a way to merge the streams via flatMap(..) and catching certain Exceptions during the execution.
Let's take the following code snippet:
public class FlatMap {
public static void main(final String[] args) {
long count;
// this might throw an exception
count = Stream.of(0.2, 0.5, 0.99).flatMap(chance -> getGenerator(chance, 20)).count();
// trying to catch the exception in flatMap() will not work
count = Stream.of(0.2, 0.5, 0.99).flatMap(chance -> {
try {
return getGenerator(chance, 20);
} catch (final NullPointerException e) {
return Stream.empty();
}
}).count();
System.out.println(count);
}
// !! we cannot change this method, we simply get a Stream
static Stream<Object> getGenerator(final double chance, final long limit) {
return Stream.generate(() -> {
if (Math.random() < chance) return new Object();
throw new NullPointerException();
}).limit(limit);
}
}
Is there any way to catch the exception of each individual Stream that was created by getGenerator(..) and simply suppress the Exception, replacing the "corrupted" Stream with an empty one or skip those elements from the specific generator Stream?

It is possible to wrap the Stream into another using the Spliterator. This method will protect a given Stream by catching the Exception and saving this state:
static <T> Stream<T> protect(final Stream<T> stream) {
final Spliterator<T> spliterator = stream.spliterator();
return StreamSupport.stream(
new Spliterators.AbstractSpliterator<T>(Long.MAX_VALUE,
spliterator.characteristics() & ~Spliterator.SIZED) {
private boolean corrupted = false;
#Override
public boolean tryAdvance(final Consumer<? super T> action) {
if (!corrupted) try {
return spliterator.tryAdvance(action);
} catch (final Exception e) {
// we suppress this one, stream ends here
corrupted = true;
}
return false;
}
}, false);
}
Then we can wrap our Stream method and safely pass it in flatMap(..):
// we protect the stream by a wrapper Stream
count = Stream.of(0.2, 0.5, 0.99)
.flatMap(chance -> protect(getGenerator(chance, 20)))
.count();

One work around is to force the Stream created by getGenerator to be evaluated within the flatMap method implementation. This forces the NullPointerException to be thrown within the try-catch block, and therefore, able to be handled.
To do this, you can collect the Stream (to a List for example):
getGenerator(chance, 20).collect(Collectors.toList()).stream()
Incorporating this into your original snippet:
public class FlatMap {
public static void main(final String[] args) {
long count;
// trying to catch the exception in flatMap() will not work
count = Stream.of(0.2, 0.5, 0.99)
.flatMap(chance -> {
try {
return getGenerator(chance, 20).collect(Collectors.toList()).stream();
}
catch (final NullPointerException e) {
return Stream.empty();
}
})
.count();
System.out.println(count);
}
// !! we cannot change this method, we simply get a Stream
static Stream<Object> getGenerator(final double chance, final long limit) {
return Stream.generate(() -> {
if (Math.random() < chance) return new Object();
throw new NullPointerException();
}).limit(limit);
}
}
Warning: this approach may reduce performance if the getGenerator Stream would be better to evaluate lazily.

Try this:
static <T> Supplier<T> getOrNull(Supplier<T> supplier) {
return () -> {
try {
return supplier.get();
} catch (Throwable e) {
return null;
}
};
}
static Stream<Object> getGenerator(final double chance, final long limit) {
return Stream.generate(
getOrNull(
() -> {
if (Math.random() < chance) return new Object();
throw new NullPointerException();
// You can throw any exception here
}))
.limit(limit)
.filter(Objects::isNull);
}
Then simply call getGenerator:
count = Stream.of(0.2, 0.5, 0.99)
.flatMap(chance -> getGenerator(chance, 20))
.count();

Related

Make a java completable future cache atomic

I've been trying to setup a simple atomic completable future cache that takes a String key and a Callable class and caches the executions and the results. I know I could use caffeine but still want to understand how this can be done without race conditions while inserting and clearing.
In this simple class I have two simplified caches: an executions cache that keeps tracks of the callables that haven't finished running, and a results cache that keeps track of the results (this will eventually be an ehcache that overflows to disk)
public class AsyncCache {
ExecutorService executor = Executors.newFixedThreadPool(10);
ConcurrentHashMap<String, CompletableFuture<Object>> executions = new ConcurrentHashMap<>();
ConcurrentHashMap<String, Object> results = new ConcurrentHashMap<>();
public CompletableFuture<Object> get(String key, Callable<Object> callable) {
Object result = results.get(key);
if (result != null) {
return CompletableFuture.completedFuture(result);
}
return executions.computeIfAbsent(key, k -> {
CompletableFuture<Object> future = CompletableFuture.supplyAsync(() -> {
try {
return callable.call();
} catch (Exception e) {
throw new CompletionException(e);
}
}, executor);
return future.whenComplete((Object r, Throwable t) -> {
if (executions.remove(k) != null) {
results.put(k, result);
}
});
});
}
public void clear() {
results.clear();
executions.clear();
}
}
I believe that this code has two problems. First, there is a synchronization problem in the lines:
if (executions.remove(k) != null) {
results.put(k, result);
}
In between remove(k) and results.put(k, result) there can be a new get call for the same key that is not already in results and has been removed from executions, thus triggering a new callable execution, when the result was about to be placed in the results cache.
Second, there is another synchronization problem in the lines:
results.clear();
executions.clear();
In between both clear() there can be a new get call that would not get result from the results map but would get a stalled response from the executions map.
Any ideas on how to fix this without naively synchronizing everything.
Edit.
What if I introduce a lock per key to guard against read and writes? Something like this:
ConcurrentMap<String, ReadWriteLock> locks = new ConcurrentHashMap<String, ReadWriteLock>();
public CompletableFuture<Object> get1(String key, Callable<Object> callable) {
ReadWriteLock reading = locks.computeIfAbsent(key, r -> new ReentrantReadWriteLock());
reading.readLock().lock();
try {
Object result = results.get(key);
if (result != null) {
return CompletableFuture.completedFuture(result);
}
return executions.computeIfAbsent(key, k -> {
CompletableFuture<Object> future = CompletableFuture.supplyAsync(() -> {
try {
return callable.call();
} catch (Exception e) {
throw new CompletionException(e);
}
}, executor);
return future.whenComplete((Object r, Throwable t) -> {
ReadWriteLock writing = locks.computeIfAbsent(k, w -> new ReentrantReadWriteLock());
writing.writeLock().lock();
try {
if (executions.remove(k) != null) {
results.put(k, r);
}
} finally {
writing.writeLock().unlock();
locks.remove(k);
}
});
});
} finally {
reading.readLock().unlock();
locks.remove(key);
}
}
This would still leave with questions regarding how to write the clear() method.
This is the code I ended up using. I have gone through many revisions but can't find any obvious deadlocks or race conditions. I'm going leave it here just in case it becomes useful for somebody else.
public class AsyncCache {
ExecutorService executor = Executors.newFixedThreadPool(10);
ConcurrentHashMap<String, CompletableFuture<Object>> executions = new ConcurrentHashMap<>();
ReentrantReadWriteLock guard = new ReentrantReadWriteLock();
MutableConfiguration<String, Object> configuration = new MutableConfiguration<>();
Cache<String, Object> results = Caching.getCachingProvider().getCacheManager().createCache("results", configuration);
public CompletableFuture<Object> get(String key, Callable<Object> callable) {
guard.readLock().lock();
try {
// Attempt to get from the cache first. Only pay attention to
// the cache eviction policies.
Object result = results.get(key);
if (result != null) {
return CompletableFuture.completedFuture(result);
}
// Attempt to get from the current executions second. Make sure
// that the cache and executions is guarded by a read write lock.
return executions.computeIfAbsent(key, k -> {
CompletableFuture<Object> future = CompletableFuture.supplyAsync(() -> {
try {
return callable.call();
} catch (Exception e) {
throw new CompletionException(e);
}
}, executor);
return future.whenComplete((Object r, Throwable t) -> {
guard.writeLock().lock();
try {
if (executions.remove(k) != null) {
if (r != null) {
results.put(k, r);
}
}
} finally {
guard.writeLock().unlock();
}
});
});
} finally {
guard.readLock().unlock();
}
}
public void clear() {
// Guard the cache and executions with a write lock.
guard.writeLock().lock();
try {
executions.clear();
results.clear();
} finally {
guard.writeLock().unlock();
}
}
}
I'm still not sure how to check if this is overly restrictive (locking more than needed). For my use case, the callables can take from 100 to 3000 milliseconds, and the clear method can be called every 15 minutes or so.
Perhaps I don't even need the executions to be a ConcurrentHashMap since the read and writes are protected.

java8 how to convert Future<T> to CompleteableFuture<T> [duplicate]

Java 8 introduces CompletableFuture, a new implementation of Future that is composable (includes a bunch of thenXxx methods). I'd like to use this exclusively, but many of the libraries I want to use return only non-composable Future instances.
Is there a way to wrap up a returned Future instances inside of a CompleteableFuture so that I can compose it?
If the library you want to use also offers a callback style method in addition to the Future style, you can provide it a handler that completes the CompletableFuture without any extra thread blocking. Like so:
AsynchronousFileChannel open = AsynchronousFileChannel.open(Paths.get("/some/file"));
// ...
CompletableFuture<ByteBuffer> completableFuture = new CompletableFuture<ByteBuffer>();
open.read(buffer, position, null, new CompletionHandler<Integer, Void>() {
#Override
public void completed(Integer result, Void attachment) {
completableFuture.complete(buffer);
}
#Override
public void failed(Throwable exc, Void attachment) {
completableFuture.completeExceptionally(exc);
}
});
completableFuture.thenApply(...)
Without the callback the only other way I see solving this is to use a polling loop that puts all your Future.isDone() checks on a single thread and then invoking complete whenever a Future is gettable.
There is a way, but you won't like it. The following method transforms a Future<T> into a CompletableFuture<T>:
public static <T> CompletableFuture<T> makeCompletableFuture(Future<T> future) {
if (future.isDone())
return transformDoneFuture(future);
return CompletableFuture.supplyAsync(() -> {
try {
if (!future.isDone())
awaitFutureIsDoneInForkJoinPool(future);
return future.get();
} catch (ExecutionException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
// Normally, this should never happen inside ForkJoinPool
Thread.currentThread().interrupt();
// Add the following statement if the future doesn't have side effects
// future.cancel(true);
throw new RuntimeException(e);
}
});
}
private static <T> CompletableFuture<T> transformDoneFuture(Future<T> future) {
CompletableFuture<T> cf = new CompletableFuture<>();
T result;
try {
result = future.get();
} catch (Throwable ex) {
cf.completeExceptionally(ex);
return cf;
}
cf.complete(result);
return cf;
}
private static void awaitFutureIsDoneInForkJoinPool(Future<?> future)
throws InterruptedException {
ForkJoinPool.managedBlock(new ForkJoinPool.ManagedBlocker() {
#Override public boolean block() throws InterruptedException {
try {
future.get();
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
return true;
}
#Override public boolean isReleasable() {
return future.isDone();
}
});
}
Obviously, the problem with this approach is, that for each Future, a thread will be blocked to wait for the result of the Future--contradicting the idea of futures. In some cases, it might be possible to do better. However, in general, there is no solution without actively wait for the result of the Future.
If your Future is the result of a call to an ExecutorService method (e.g. submit()), the easiest would be to use the CompletableFuture.runAsync(Runnable, Executor) method instead.
From
Runnbale myTask = ... ;
Future<?> future = myExecutor.submit(myTask);
to
Runnbale myTask = ... ;
CompletableFuture<?> future = CompletableFuture.runAsync(myTask, myExecutor);
The CompletableFuture is then created "natively".
EDIT: Pursuing comments by #SamMefford corrected by #MartinAndersson, if you want to pass a Callable, you need to call supplyAsync(), converting the Callable<T> into a Supplier<T>, e.g. with:
CompletableFuture.supplyAsync(() -> {
try { return myCallable.call(); }
catch (Exception ex) { throw new CompletionException(ex); } // Or return default value
}, myExecutor);
Because T Callable.call() throws Exception; throws an exception and T Supplier.get(); doesn't, you have to catch the exception so prototypes are compatible.
A note on exception handling
The get() method doesn't specify a throws, which means it should not throw a checked exception. However, unchecked exception can be used. The code in CompletableFuture shows that CompletionException is used and is unchecked (i.e. is a RuntimeException), hence the catch/throw wrapping any exception into a CompletionException.
Also, as #WeGa indicated, you can use the handle() method to deal with exceptions potentially being thrown by the result:
CompletableFuture<T> future = CompletableFuture.supplyAsync(...);
future.handle((ex,res) -> {
if (ex != null) {
// An exception occurred ...
} else {
// No exception was thrown, 'res' is valid and can be handled here
}
});
I published a little futurity project that tries to do better than the straightforward way in the answer.
The main idea is to use only one thread (and of course with not just a spin loop) to check all Futures states inside, which helps to avoid blocking a thread from a pool for each Future -> CompletableFuture transformation.
Usage example:
Future oldFuture = ...;
CompletableFuture profit = Futurity.shift(oldFuture);
Suggestion:
http://www.thedevpiece.com/converting-old-java-future-to-completablefuture/
But, basically:
public class CompletablePromiseContext {
private static final ScheduledExecutorService SERVICE = Executors.newSingleThreadScheduledExecutor();
public static void schedule(Runnable r) {
SERVICE.schedule(r, 1, TimeUnit.MILLISECONDS);
}
}
And, the CompletablePromise:
public class CompletablePromise<V> extends CompletableFuture<V> {
private Future<V> future;
public CompletablePromise(Future<V> future) {
this.future = future;
CompletablePromiseContext.schedule(this::tryToComplete);
}
private void tryToComplete() {
if (future.isDone()) {
try {
complete(future.get());
} catch (InterruptedException e) {
completeExceptionally(e);
} catch (ExecutionException e) {
completeExceptionally(e.getCause());
}
return;
}
if (future.isCancelled()) {
cancel(true);
return;
}
CompletablePromiseContext.schedule(this::tryToComplete);
}
}
Example:
public class Main {
public static void main(String[] args) {
final ExecutorService service = Executors.newSingleThreadExecutor();
final Future<String> stringFuture = service.submit(() -> "success");
final CompletableFuture<String> completableFuture = new CompletablePromise<>(stringFuture);
completableFuture.whenComplete((result, failure) -> {
System.out.println(result);
});
}
}
Let me suggest another (hopefully, better) option:
https://github.com/vsilaev/java-async-await/tree/master/com.farata.lang.async.examples/src/main/java/com/farata/concurrent
Briefly, the idea is the following:
Introduce CompletableTask<V> interface -- the union of the
CompletionStage<V> + RunnableFuture<V>
Warp ExecutorService to return CompletableTask from submit(...) methods (instead of Future<V>)
Done, we have runnable AND composable Futures.
Implementation uses an alternative CompletionStage implementation (pay attention, CompletionStage rather than CompletableFuture):
Usage:
J8ExecutorService exec = J8Executors.newCachedThreadPool();
CompletionStage<String> = exec
.submit( someCallableA )
.thenCombineAsync( exec.submit(someCallableB), (a, b) -> a + " " + b)
.thenCombine( exec.submit(someCallableC), (ab, b) -> ab + " " + c);
public static <T> CompletableFuture<T> fromFuture(Future<T> f) {
return CompletableFuture.completedFuture(null).thenCompose(avoid -> {
try {
return CompletableFuture.completedFuture(f.get());
} catch (InterruptedException e) {
return CompletableFuture.failedFuture(e);
} catch (ExecutionException e) {
return CompletableFuture.failedFuture(e.getCause());
}
});
}
The main idea goes like this:
Future<?> future = null;
return CompletableFuture.supplyAsync(future::get);
However, you will receive some warnings from your compiler.
So, here is the first option.
Future<?> future = null;
return CompletableFuture.supplyAsync(
()->{
try {
return future.get();
} catch (Exception e) {
throw new RuntimeException(e);
}
});
Second Option, hide the try...catch via casting the functional interface.
#FunctionalInterface
public interface MySupplier<T> extends Supplier<T> {
#Override
default T get() {
try {
return getInternal();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
T getInternal() throws Exception;
}
public static void main(String[] args) {
Future<?> future = null;
return CompletableFuture.supplyAsync((MySupplier<?>) future::get);
}
Third Option, find out some 3rd party lib which has provided such a functional interface.
See Also: Java 8 Lambda function that throws exception?

How to execute an Array of CompletableFuture and compose their results

I am investigating Java 8 CompletableFutures and read (and seen) that I should employ thenCompose instead of thenApply.
I have converted my code to use thenCompose but I have a feeling in an incorrect manner.
Here is my controlling code...
final CompletableFuture<List<String>> extractor = get(htmlPageSource);
#SuppressWarnings("unchecked")
final CompletableFuture<List<Documentable>>[] completableFutures =
new CompletableFuture[ENDPOINT.EXTRACTABLES.size()];
int index = 0;
for( ENDPOINT endpoint : ENDPOINT.EXTRACTABLES ) {
final CompletableFuture<List<Documentable>> metaData =
extractor.thenComposeAsync(
s -> endpoint.contactEndpoit(s), executorService );
completableFutures[index++] = metaData.exceptionally(x -> failedList(x));
}
CompletableFuture
.allOf( completableFutures )
.thenComposeAsync( dummy -> combineDocuments( completableFutures ))
.thenAccept ( x -> finish( x ))
.exceptionally( x -> failed( x ));
private List<Documentable> failedList(final Throwable x) {
LOGGER.error("failedList", x);
final List<Documentable> metaData = new ArrayList<>();
return metaData;
}
private Void failed(final Throwable x) {
LOGGER.error("failed", x);
return null;
}
Which I believe is acceptable
However the code that makes me uneasy is this:-
WWW_SITE_ONE("https://example.site.one/") {
#Override
public <T extends Documentable> CompletionStage<List<T>> contactEndpoit( final List<String> elements) {
LOGGER.info("WWW_SITE_ONE " + Thread.currentThread().getName());
final List<T> SITE_ONEs = new ArrayList<>();
for (final String element : elements) {
try {
final String json = Jsoup.connect(ENDPOINT.WWW_SITE_ONE.getBaseUrl() + element).ignoreContentType(true).ignoreHttpErrors(true).maxBodySize(0).timeout(60000).execute().body();
if (json.contains("errors")) {
continue;
}
final T SITE_ONE = OBJECT_READER_SITE_ONE.readValue(json);
SITE_ONEs.add(SITE_ONE);
}
catch( final Throwable e ) {
LOGGER.error("WWW_SITE_ONE failed", e);
throw new RuntimeException(e);
}
}
return CompletableFuture.supplyAsync(() -> SITE_ONEs);
}
},
WWW_SITE_TWO("https://example.site.two/") {
#Override
public <T extends Documentable> CompletionStage<List<T>> contactEndpoit(final List<String> elements) {
LOGGER.info("WWW_SITE_TWO " + Thread.currentThread().getName());
final List<T> SITE_TWOs = new ArrayList<>();
for (final String element : elements) {
try {
final String json = Jsoup.connect(ENDPOINT.WWW_SITE_TWO.getBaseUrl() + element).ignoreContentType(true).ignoreHttpErrors(true).maxBodySize(0).timeout(60000).execute().body();
if (json.equals("Resource not found.")) {
continue;
}
final T SITE_TWO = OBJECT_READER_SITE_TWO.readValue(json);
SITE_TWOs.add(SITE_TWO);
}
catch (final Throwable e) {
LOGGER.error("WWW_SITE_TWO failed", e);
throw new RuntimeException(e);
}
}
return CompletableFuture.supplyAsync(() -> SITE_TWOs);
}
},
WWW_SITE_THREE("https://example.site.three/") {
#Override
public <T extends Documentable> CompletionStage<List<T>> contactEndpoit(final List<String> elements) {
LOGGER.info("WWW_SITE_THREE " + Thread.currentThread().getName());
final List<T> SITE_THREEs = new ArrayList<>();
for (final String element : elements) {
try {
final String SITE_THREEJsonString = Jsoup
.connect( ENDPOINT.WWW_SITE_THREE.getBaseUrl() + element)
.ignoreContentType(true)
.ignoreHttpErrors(true)
.maxBodySize(0)
.timeout(60000)
.execute()
.body();
final SITE_THREE SITE_THREE_Json = OBJECT_READER_SITE_THREE.readValue(SITE_THREEJsonString);
final T SITE_THREE = (T) SITE_THREE_Json;
if (SITE_THREE_Json.getHitCount() > 0) {
SITE_THREEs.add(SITE_THREE);
}
}
catch (final Throwable e) {
LOGGER.error("WWW_SITE_THREE failed", e);
throw new RuntimeException(e);
}
}
return CompletableFuture.supplyAsync(() -> SITE_THREEs);
}
};
Its where I am returning CompletableFuture.supplyAsync(() -> SITE_THREEs);
Is this the correct approach?
Or does this start another asynchronous thread to simply return my List<>?
As the name suggests, supplyAsync will perform an asynchronous operation, executing the Supplier’s get() method, hence the body of the lambda expression, in a background thread, regardless of how trivial it is. Since the implementation of supplyAsync has no way to check how trivial the code encapsulated by the Supplier is, it has to work this way.
Instead of CompletableFuture.supplyAsync(() -> SITE_THREEs), you should use CompletableFuture.completedFuture(SITE_THREEs) which returns a future that has already been completed with the result, hence, not requiring additional actions.
If the method only returns completed stages or throws an exception, you may also change it to return the result value instead of a CompletionStage and use thenApply instead of thenCompose, simplifying your code—unless you want to keep the option of introducing asynchronous operations in a future version of that method.

Using exceptions with Google Guava

What is the best pattern for using Google Guava with methods that should throw exceptions?
Let's say I have:
public Sting someMethod(Integer i) throws SomeException;
And I want to do:
List<String> s=Lists.transform(is,new Function<String, Integer>() {
public String apply(Integer i) {
return someMethod(i);
}
});
I couldn't do the above because of the exception. Is there any nice pattern for handling it?
Propagate the checked exception as a RuntimeException:
try {
return someMethod(i);
} catch (SomeException e) {
throw new RuntimeException(e);
}
EDIT: Since the transformed list is lazily evaluated, the exception won't be thrown until you access the list elements. You can force the evaluation by copying the transformed list into a new list, like:
s = new ArrayList<>(s);
You could wrap that in a try-catch block that catches RuntimeException and handles it however you want; your original SomeException instance can be obtained by calling getCause() on the RuntimeException. Or you could just let the RuntimeException bubble up.
You can use
public interface FunctionWithException<T, R, E extends Exception> {
public R apply(T t) throws E;
}
It depends on how you want to handle the exception.
Stop the list transformation when an exception occurs: See #dnault's answer.
Continue the list transformation and remove the element which caused exception (and log some error message).
In this case, we will return null when an exception occurs, this null value will be removed from final list:
List<String> s = Lists.newArrayList(
Iterables.filter(
Iterables.transform(l, new Function<Integer, String>() {
#Override
public String apply(Integer i) {
try {
return someMethod(i);
} catch (SomeException e) {
e.printStackTrace();
return null;
}
}
}), Predicates.notNull()))`
EDIT
If someMethod can return null value then you should a wrapper like this one:
class Wrapper {
public Exception exception = null;
public String result = null;
}
The list transformation will then be:
List<Wrapper> wrappers = Lists.newArrayList(
Iterables.filter(
Iterables.transform(l, new Function<Integer, Wrapper>() {
#Override
public Wrapper apply(Integer i) {
Wrapper wrapper = new Wrapper();
try {
wrapper.result = someMethod(i);
} catch (SomeException e) {
wrapper.exception = e;
}
return wrapper;
}
}), new Predicate<Wrapper>() {
#Override
public boolean apply(Wrapper wrapper) {
return wrapper.exception == null;
}
}));

Transform Java Future into a CompletableFuture

Java 8 introduces CompletableFuture, a new implementation of Future that is composable (includes a bunch of thenXxx methods). I'd like to use this exclusively, but many of the libraries I want to use return only non-composable Future instances.
Is there a way to wrap up a returned Future instances inside of a CompleteableFuture so that I can compose it?
If the library you want to use also offers a callback style method in addition to the Future style, you can provide it a handler that completes the CompletableFuture without any extra thread blocking. Like so:
AsynchronousFileChannel open = AsynchronousFileChannel.open(Paths.get("/some/file"));
// ...
CompletableFuture<ByteBuffer> completableFuture = new CompletableFuture<ByteBuffer>();
open.read(buffer, position, null, new CompletionHandler<Integer, Void>() {
#Override
public void completed(Integer result, Void attachment) {
completableFuture.complete(buffer);
}
#Override
public void failed(Throwable exc, Void attachment) {
completableFuture.completeExceptionally(exc);
}
});
completableFuture.thenApply(...)
Without the callback the only other way I see solving this is to use a polling loop that puts all your Future.isDone() checks on a single thread and then invoking complete whenever a Future is gettable.
There is a way, but you won't like it. The following method transforms a Future<T> into a CompletableFuture<T>:
public static <T> CompletableFuture<T> makeCompletableFuture(Future<T> future) {
if (future.isDone())
return transformDoneFuture(future);
return CompletableFuture.supplyAsync(() -> {
try {
if (!future.isDone())
awaitFutureIsDoneInForkJoinPool(future);
return future.get();
} catch (ExecutionException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
// Normally, this should never happen inside ForkJoinPool
Thread.currentThread().interrupt();
// Add the following statement if the future doesn't have side effects
// future.cancel(true);
throw new RuntimeException(e);
}
});
}
private static <T> CompletableFuture<T> transformDoneFuture(Future<T> future) {
CompletableFuture<T> cf = new CompletableFuture<>();
T result;
try {
result = future.get();
} catch (Throwable ex) {
cf.completeExceptionally(ex);
return cf;
}
cf.complete(result);
return cf;
}
private static void awaitFutureIsDoneInForkJoinPool(Future<?> future)
throws InterruptedException {
ForkJoinPool.managedBlock(new ForkJoinPool.ManagedBlocker() {
#Override public boolean block() throws InterruptedException {
try {
future.get();
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
return true;
}
#Override public boolean isReleasable() {
return future.isDone();
}
});
}
Obviously, the problem with this approach is, that for each Future, a thread will be blocked to wait for the result of the Future--contradicting the idea of futures. In some cases, it might be possible to do better. However, in general, there is no solution without actively wait for the result of the Future.
If your Future is the result of a call to an ExecutorService method (e.g. submit()), the easiest would be to use the CompletableFuture.runAsync(Runnable, Executor) method instead.
From
Runnbale myTask = ... ;
Future<?> future = myExecutor.submit(myTask);
to
Runnbale myTask = ... ;
CompletableFuture<?> future = CompletableFuture.runAsync(myTask, myExecutor);
The CompletableFuture is then created "natively".
EDIT: Pursuing comments by #SamMefford corrected by #MartinAndersson, if you want to pass a Callable, you need to call supplyAsync(), converting the Callable<T> into a Supplier<T>, e.g. with:
CompletableFuture.supplyAsync(() -> {
try { return myCallable.call(); }
catch (Exception ex) { throw new CompletionException(ex); } // Or return default value
}, myExecutor);
Because T Callable.call() throws Exception; throws an exception and T Supplier.get(); doesn't, you have to catch the exception so prototypes are compatible.
A note on exception handling
The get() method doesn't specify a throws, which means it should not throw a checked exception. However, unchecked exception can be used. The code in CompletableFuture shows that CompletionException is used and is unchecked (i.e. is a RuntimeException), hence the catch/throw wrapping any exception into a CompletionException.
Also, as #WeGa indicated, you can use the handle() method to deal with exceptions potentially being thrown by the result:
CompletableFuture<T> future = CompletableFuture.supplyAsync(...);
future.handle((ex,res) -> {
if (ex != null) {
// An exception occurred ...
} else {
// No exception was thrown, 'res' is valid and can be handled here
}
});
I published a little futurity project that tries to do better than the straightforward way in the answer.
The main idea is to use only one thread (and of course with not just a spin loop) to check all Futures states inside, which helps to avoid blocking a thread from a pool for each Future -> CompletableFuture transformation.
Usage example:
Future oldFuture = ...;
CompletableFuture profit = Futurity.shift(oldFuture);
Suggestion:
http://www.thedevpiece.com/converting-old-java-future-to-completablefuture/
But, basically:
public class CompletablePromiseContext {
private static final ScheduledExecutorService SERVICE = Executors.newSingleThreadScheduledExecutor();
public static void schedule(Runnable r) {
SERVICE.schedule(r, 1, TimeUnit.MILLISECONDS);
}
}
And, the CompletablePromise:
public class CompletablePromise<V> extends CompletableFuture<V> {
private Future<V> future;
public CompletablePromise(Future<V> future) {
this.future = future;
CompletablePromiseContext.schedule(this::tryToComplete);
}
private void tryToComplete() {
if (future.isDone()) {
try {
complete(future.get());
} catch (InterruptedException e) {
completeExceptionally(e);
} catch (ExecutionException e) {
completeExceptionally(e.getCause());
}
return;
}
if (future.isCancelled()) {
cancel(true);
return;
}
CompletablePromiseContext.schedule(this::tryToComplete);
}
}
Example:
public class Main {
public static void main(String[] args) {
final ExecutorService service = Executors.newSingleThreadExecutor();
final Future<String> stringFuture = service.submit(() -> "success");
final CompletableFuture<String> completableFuture = new CompletablePromise<>(stringFuture);
completableFuture.whenComplete((result, failure) -> {
System.out.println(result);
});
}
}
Let me suggest another (hopefully, better) option:
https://github.com/vsilaev/java-async-await/tree/master/com.farata.lang.async.examples/src/main/java/com/farata/concurrent
Briefly, the idea is the following:
Introduce CompletableTask<V> interface -- the union of the
CompletionStage<V> + RunnableFuture<V>
Warp ExecutorService to return CompletableTask from submit(...) methods (instead of Future<V>)
Done, we have runnable AND composable Futures.
Implementation uses an alternative CompletionStage implementation (pay attention, CompletionStage rather than CompletableFuture):
Usage:
J8ExecutorService exec = J8Executors.newCachedThreadPool();
CompletionStage<String> = exec
.submit( someCallableA )
.thenCombineAsync( exec.submit(someCallableB), (a, b) -> a + " " + b)
.thenCombine( exec.submit(someCallableC), (ab, b) -> ab + " " + c);
public static <T> CompletableFuture<T> fromFuture(Future<T> f) {
return CompletableFuture.completedFuture(null).thenCompose(avoid -> {
try {
return CompletableFuture.completedFuture(f.get());
} catch (InterruptedException e) {
return CompletableFuture.failedFuture(e);
} catch (ExecutionException e) {
return CompletableFuture.failedFuture(e.getCause());
}
});
}
The main idea goes like this:
Future<?> future = null;
return CompletableFuture.supplyAsync(future::get);
However, you will receive some warnings from your compiler.
So, here is the first option.
Future<?> future = null;
return CompletableFuture.supplyAsync(
()->{
try {
return future.get();
} catch (Exception e) {
throw new RuntimeException(e);
}
});
Second Option, hide the try...catch via casting the functional interface.
#FunctionalInterface
public interface MySupplier<T> extends Supplier<T> {
#Override
default T get() {
try {
return getInternal();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
T getInternal() throws Exception;
}
public static void main(String[] args) {
Future<?> future = null;
return CompletableFuture.supplyAsync((MySupplier<?>) future::get);
}
Third Option, find out some 3rd party lib which has provided such a functional interface.
See Also: Java 8 Lambda function that throws exception?

Categories

Resources