Class FluentFuture<V extends @Nullable java.lang.Object>
- java.lang.Object
-
- com.google.common.util.concurrent.internal.InternalFutureFailureAccess
-
- com.google.common.util.concurrent.AbstractFuture<V>
-
- com.google.common.util.concurrent.FluentFuture<V>
-
- All Implemented Interfaces:
ListenableFuture<V>,java.util.concurrent.Future<V>
@DoNotMock("Use FluentFuture.from(Futures.immediate*Future) or SettableFuture") @GwtCompatible(emulated=true) public abstract class FluentFuture<V extends @Nullable java.lang.Object> extends AbstractFuture<V>
AListenableFuturethat supports fluent chains of operations. For example:ListenableFuture<Boolean> adminIsLoggedIn = FluentFuture.from(usersDatabase.getAdminUser()) .transform(User::getId, directExecutor()) .transform(ActivityService::isLoggedIn, threadPool) .catching(RpcException.class, e -> false, directExecutor());Alternatives
Frameworks
When chaining together a graph of asynchronous operations, you will often find it easier to use a framework. Frameworks automate the process, often adding features like monitoring, debugging, and cancellation. Examples of frameworks include:
CompletableFuture/CompletionStageUsers of
CompletableFuturewill likely want to continue usingCompletableFuture.FluentFutureis targeted at people who useListenableFuture, who can't use Java 8, or who want an API more focused thanCompletableFuture. (If you need to adapt betweenCompletableFutureandListenableFuture, consider Future Converter.)Extension
If you want a class likeFluentFuturebut with extra methods, we recommend declaring your own subclass ofListenableFuture, complete with a method likefrom(com.google.common.util.concurrent.ListenableFuture<V>)to adapt an existingListenableFuture, implemented atop aForwardingListenableFuturethat forwards to that future and adds the desired methods.- Since:
- 23.0
-
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Deprecated Methods Modifier and Type Method Description voidaddCallback(FutureCallback<? super V> callback, java.util.concurrent.Executor executor)Registers separate success and failure callbacks to be run when thisFuture's computation is complete or, if the computation is already complete, immediately.<X extends java.lang.Throwable>
FluentFuture<V>catching(java.lang.Class<X> exceptionType, Function<? super X,? extends V> fallback, java.util.concurrent.Executor executor)Returns aFuturewhose result is taken from thisFutureor, if thisFuturefails with the givenexceptionType, from the result provided by thefallback.<X extends java.lang.Throwable>
FluentFuture<V>catchingAsync(java.lang.Class<X> exceptionType, AsyncFunction<? super X,? extends V> fallback, java.util.concurrent.Executor executor)Returns aFuturewhose result is taken from thisFutureor, if thisFuturefails with the givenexceptionType, from the result provided by thefallback.static <V extends @Nullable java.lang.Object>
FluentFuture<V>from(FluentFuture<V> future)Deprecated.no need to use thisstatic <V extends @Nullable java.lang.Object>
FluentFuture<V>from(ListenableFuture<V> future)Converts the givenListenableFutureto an equivalentFluentFuture.<T extends @Nullable java.lang.Object>
FluentFuture<T>transform(Function<? super V,T> function, java.util.concurrent.Executor executor)Returns a newFuturewhose result is derived from the result of thisFuture.<T extends @Nullable java.lang.Object>
FluentFuture<T>transformAsync(AsyncFunction<? super V,T> function, java.util.concurrent.Executor executor)Returns a newFuturewhose result is asynchronously derived from the result of thisFuture.FluentFuture<V>withTimeout(long timeout, java.util.concurrent.TimeUnit unit, java.util.concurrent.ScheduledExecutorService scheduledExecutor)Returns a future that delegates to this future but will finish early (via aTimeoutExceptionwrapped in anExecutionException) if the specified timeout expires.FluentFuture<V>withTimeout(java.time.Duration timeout, java.util.concurrent.ScheduledExecutorService scheduledExecutor)Returns a future that delegates to this future but will finish early (via aTimeoutExceptionwrapped in anExecutionException) if the specified timeout expires.-
Methods inherited from class com.google.common.util.concurrent.AbstractFuture
addListener, afterDone, cancel, get, get, interruptTask, isCancelled, isDone, pendingToString, set, setException, setFuture, toString, tryInternalFastPathGetFailure, wasInterrupted
-
-
-
-
Method Detail
-
from
public static <V extends @Nullable java.lang.Object> FluentFuture<V> from(ListenableFuture<V> future)
Converts the givenListenableFutureto an equivalentFluentFuture.If the given
ListenableFutureis already aFluentFuture, it is returned directly. If not, it is wrapped in aFluentFuturethat delegates all calls to the originalListenableFuture.
-
from
@Deprecated public static <V extends @Nullable java.lang.Object> FluentFuture<V> from(FluentFuture<V> future)
Deprecated.no need to use thisSimply returns its argument.- Since:
- 28.0
-
catching
@GwtIncompatible("AVAILABLE but requires exceptionType to be Throwable.class") public final <X extends java.lang.Throwable> FluentFuture<V> catching(java.lang.Class<X> exceptionType, Function<? super X,? extends V> fallback, java.util.concurrent.Executor executor)Returns aFuturewhose result is taken from thisFutureor, if thisFuturefails with the givenexceptionType, from the result provided by thefallback.Function.apply(F)is not invoked until the primary input has failed, so if the primary input succeeds, it is never invoked. If, during the invocation offallback, an exception is thrown, this exception is used as the result of the outputFuture.Usage example:
// Falling back to a zero counter in case an exception happens when processing the RPC to fetch // counters. ListenableFuture<Integer> faultTolerantFuture = fetchCounters().catching(FetchException.class, x -> 0, directExecutor());When selecting an executor, note that
directExecutoris dangerous in some cases. See the discussion in theAbstractFuture.addListener(java.lang.Runnable, java.util.concurrent.Executor)documentation. All its warnings about heavyweight listeners are also applicable to heavyweight functions passed to this method.This method is similar to
CompletableFuture.exceptionally(java.util.function.Function<java.lang.Throwable, ? extends T>). It can also serve some of the use cases ofCompletableFuture.handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>)andCompletableFuture.handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>)when used along withtransform(com.google.common.base.Function<? super V, T>, java.util.concurrent.Executor).- Parameters:
exceptionType- the exception type that triggers use offallback. The exception type is matched against the input's exception. "The input's exception" means the cause of theExecutionExceptionthrown byinput.get()or, ifget()throws a different kind of exception, that exception itself. To avoid hiding bugs and other unrecoverable errors, callers should prefer more specific types, avoidingThrowable.classin particular.fallback- theFunctionto be called if the input fails with the expected exception type. The function's argument is the input's exception. "The input's exception" means the cause of theExecutionExceptionthrown bythis.get()or, ifget()throws a different kind of exception, that exception itself.executor- the executor that runsfallbackif the input fails
-
catchingAsync
@GwtIncompatible("AVAILABLE but requires exceptionType to be Throwable.class") public final <X extends java.lang.Throwable> FluentFuture<V> catchingAsync(java.lang.Class<X> exceptionType, AsyncFunction<? super X,? extends V> fallback, java.util.concurrent.Executor executor)Returns aFuturewhose result is taken from thisFutureor, if thisFuturefails with the givenexceptionType, from the result provided by thefallback.AsyncFunction.apply(I)is not invoked until the primary input has failed, so if the primary input succeeds, it is never invoked. If, during the invocation offallback, an exception is thrown, this exception is used as the result of the outputFuture.Usage examples:
// Falling back to a zero counter in case an exception happens when processing the RPC to fetch // counters. ListenableFuture<Integer> faultTolerantFuture = fetchCounters().catchingAsync( FetchException.class, x -> immediateFuture(0), directExecutor());The fallback can also choose to propagate the original exception when desired:
// Falling back to a zero counter only in case the exception was a // TimeoutException. ListenableFuture<Integer> faultTolerantFuture = fetchCounters().catchingAsync( FetchException.class, e -> { if (omitDataOnFetchFailure) { return immediateFuture(0); } throw e; }, directExecutor());When selecting an executor, note that
directExecutoris dangerous in some cases. See the discussion in theAbstractFuture.addListener(java.lang.Runnable, java.util.concurrent.Executor)documentation. All its warnings about heavyweight listeners are also applicable to heavyweight functions passed to this method. (Specifically,directExecutorfunctions should avoid heavyweight operations insideAsyncFunction.apply. Any heavyweight operations should occur in other threads responsible for completing the returnedFuture.)This method is similar to
CompletableFuture.exceptionally(java.util.function.Function<java.lang.Throwable, ? extends T>). It can also serve some of the use cases ofCompletableFuture.handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>)andCompletableFuture.handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>)when used along withtransform(com.google.common.base.Function<? super V, T>, java.util.concurrent.Executor).- Parameters:
exceptionType- the exception type that triggers use offallback. The exception type is matched against the input's exception. "The input's exception" means the cause of theExecutionExceptionthrown bythis.get()or, ifget()throws a different kind of exception, that exception itself. To avoid hiding bugs and other unrecoverable errors, callers should prefer more specific types, avoidingThrowable.classin particular.fallback- theAsyncFunctionto be called if the input fails with the expected exception type. The function's argument is the input's exception. "The input's exception" means the cause of theExecutionExceptionthrown byinput.get()or, ifget()throws a different kind of exception, that exception itself.executor- the executor that runsfallbackif the input fails
-
withTimeout
@GwtIncompatible public final FluentFuture<V> withTimeout(java.time.Duration timeout, java.util.concurrent.ScheduledExecutorService scheduledExecutor)
Returns a future that delegates to this future but will finish early (via aTimeoutExceptionwrapped in anExecutionException) if the specified timeout expires. If the timeout expires, not only will the output future finish, but also the input future (this) will be cancelled and interrupted.- Parameters:
timeout- when to time out the futurescheduledExecutor- The executor service to enforce the timeout.- Since:
- 28.0
-
withTimeout
@GwtIncompatible public final FluentFuture<V> withTimeout(long timeout, java.util.concurrent.TimeUnit unit, java.util.concurrent.ScheduledExecutorService scheduledExecutor)
Returns a future that delegates to this future but will finish early (via aTimeoutExceptionwrapped in anExecutionException) if the specified timeout expires. If the timeout expires, not only will the output future finish, but also the input future (this) will be cancelled and interrupted.- Parameters:
timeout- when to time out the futureunit- the time unit of the time parameterscheduledExecutor- The executor service to enforce the timeout.
-
transformAsync
public final <T extends @Nullable java.lang.Object> FluentFuture<T> transformAsync(AsyncFunction<? super V,T> function, java.util.concurrent.Executor executor)
Returns a newFuturewhose result is asynchronously derived from the result of thisFuture. If the inputFuturefails, the returnedFuturefails with the same exception (and the function is not invoked).More precisely, the returned
Futuretakes its result from aFutureproduced by applying the givenAsyncFunctionto the result of the originalFuture. Example usage:FluentFuture<RowKey> rowKeyFuture = FluentFuture.from(indexService.lookUp(query)); ListenableFuture<QueryResult> queryFuture = rowKeyFuture.transformAsync(dataService::readFuture, executor);When selecting an executor, note that
directExecutoris dangerous in some cases. See the discussion in theAbstractFuture.addListener(java.lang.Runnable, java.util.concurrent.Executor)documentation. All its warnings about heavyweight listeners are also applicable to heavyweight functions passed to this method. (Specifically,directExecutorfunctions should avoid heavyweight operations insideAsyncFunction.apply. Any heavyweight operations should occur in other threads responsible for completing the returnedFuture.)The returned
Futureattempts to keep its cancellation state in sync with that of the input future and that of the future returned by the chain function. That is, if the returnedFutureis cancelled, it will attempt to cancel the other two, and if either of the other two is cancelled, the returnedFuturewill receive a callback in which it will attempt to cancel itself.This method is similar to
CompletableFuture.thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>)andCompletableFuture.thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>). It can also serve some of the use cases ofCompletableFuture.handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>)andCompletableFuture.handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>)when used along withcatching(java.lang.Class<X>, com.google.common.base.Function<? super X, ? extends V>, java.util.concurrent.Executor).- Parameters:
function- A function to transform the result of this future to the result of the output futureexecutor- Executor to run the function in.- Returns:
- A future that holds result of the function (if the input succeeded) or the original input's failure (if not)
-
transform
public final <T extends @Nullable java.lang.Object> FluentFuture<T> transform(Function<? super V,T> function, java.util.concurrent.Executor executor)
Returns a newFuturewhose result is derived from the result of thisFuture. If this inputFuturefails, the returnedFuturefails with the same exception (and the function is not invoked). Example usage:ListenableFuture<List<Row>> rowsFuture = queryFuture.transform(QueryResult::getRows, executor);When selecting an executor, note that
directExecutoris dangerous in some cases. See the discussion in theAbstractFuture.addListener(java.lang.Runnable, java.util.concurrent.Executor)documentation. All its warnings about heavyweight listeners are also applicable to heavyweight functions passed to this method.The returned
Futureattempts to keep its cancellation state in sync with that of the input future. That is, if the returnedFutureis cancelled, it will attempt to cancel the input, and if the input is cancelled, the returnedFuturewill receive a callback in which it will attempt to cancel itself.An example use of this method is to convert a serializable object returned from an RPC into a POJO.
This method is similar to
CompletableFuture.thenApply(java.util.function.Function<? super T, ? extends U>)andCompletableFuture.thenApplyAsync(java.util.function.Function<? super T, ? extends U>). It can also serve some of the use cases ofCompletableFuture.handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>)andCompletableFuture.handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>)when used along withcatching(java.lang.Class<X>, com.google.common.base.Function<? super X, ? extends V>, java.util.concurrent.Executor).- Parameters:
function- A Function to transform the results of this future to the results of the returned future.executor- Executor to run the function in.- Returns:
- A future that holds result of the transformation.
-
addCallback
public final void addCallback(FutureCallback<? super V> callback, java.util.concurrent.Executor executor)
Registers separate success and failure callbacks to be run when thisFuture's computation is complete or, if the computation is already complete, immediately.The callback is run on
executor. There is no guaranteed ordering of execution of callbacks, but any callback added through this method is guaranteed to be called once the computation is complete.Example:
future.addCallback( new FutureCallback<QueryResult>() { public void onSuccess(QueryResult result) { storeInCache(result); } public void onFailure(Throwable t) { reportError(t); } }, executor);When selecting an executor, note that
directExecutoris dangerous in some cases. See the discussion in theAbstractFuture.addListener(java.lang.Runnable, java.util.concurrent.Executor)documentation. All its warnings about heavyweight listeners are also applicable to heavyweight callbacks passed to this method.For a more general interface to attach a completion listener, see
AbstractFuture.addListener(java.lang.Runnable, java.util.concurrent.Executor).This method is similar to
CompletableFuture.whenComplete(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>)andCompletableFuture.whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>). It also serves the use case ofCompletableFuture.thenAccept(java.util.function.Consumer<? super T>)andCompletableFuture.thenAcceptAsync(java.util.function.Consumer<? super T>).- Parameters:
callback- The callback to invoke when thisFutureis completed.executor- The executor to runcallbackwhen the future completes.
-
-