Regarding handling exceptions in the following code:
ListenableFuture<BufferedImage> imgFuture = downloadExecutor
.submit(new Downloader(url));
ListenableFuture<BufferedImage> resizeFuture = Futures.transformAsync(
imgFuture, new AsyncFunction<BufferedImage, BufferedImage>()
{
@Override
public ListenableFuture<BufferedImage> apply(
BufferedImage input) throws Exception
{
ListenableFuture<BufferedImage> resizedFuture = null;
if (input != null)
{
resizedFuture = actionExecutor
.submit(new ResizeImageAction(input));
}
return resizedFuture;
}
});
ListenableFuture<BufferedImage> grayFuture = Futures
.transformAsync(resizeFuture, input -> {
return actionExecutor
.submit(new ToGrayImageAction(input));
});
Assuming that every action sumbitted to an executor can raise an exception, how will this code behave.
Does the transformAsync()
method knows to not chain nulls or futures that raised exceptions?? Will using CheckedFuture
help me here? If so, how should I use it?
It knows about thrown exception, but doesn't know about nulls because it's perfectly legal value. If exception will be thrown in the first ListenableFuture
, then it will be propagated to the all transformers: their onFailure
callbacks will be invoked, but not their transformation (because there is no value to transform).
Javadoc to transformAsync
:
@return A future that holds result of the function (if the input succeeded) or the original input's failure (if not)
Simple example:
ListenableFuture<Integer> nullFuture = executor.submit(() -> null);
ListenableFuture<Integer> exceptionFuture = executor.submit(() -> {
throw new RuntimeException();
});
// Replace first argument with exceptionFuture to get another result
ListenableFuture<Integer> transformer = Futures.transformAsync(nullFuture, i -> {
System.out.println(i);
return Futures.immediateCheckedFuture(1);
}, executor);
Futures.addCallback(transformer, new FutureCallback<Integer>() {
@Override
public void onSuccess(Integer result) {
System.out.println(result);
}
@Override
public void onFailure(Throwable t) {
System.out.println(t);
}
});
For the nullFuture
"null and 1" will be printed, whereas for exceptionFuture
only "java.lang.RuntimeException" will be printed, because exception was propagated to its transformer.