How to Guard Asynchronous Methods
SmallRye Fault Tolerance allows offloading method calls to another thread, as well as applying asynchronous fault tolerance.
Asynchronous fault tolerance means guarding not just the synchronous method execution, but the entire asynchronous operation started by the method call, until the result is delivered. For example:
CompletionStage<String> doSomething() {
return CompletableFuture.supplyAsync(() -> {
if (someCondition) {
return someValue;
} else {
throw someException;
}
});
}
This method always returns a CompletionStage and it never throws an exception.
However, if someCondition does not hold, the CompletionStage returned from the method will complete exceptionally.
Ordinary (non-asynchronous) fault tolerance:
-
never considers this operation failing, because the method returns a value and does not throw an exception;
-
considers this operation finished when the method returns.
Asynchronous fault tolerance, on the other hand:
-
defers its decision process to the moment when the returned
CompletionStagecompletes, -
and considers this operation running until that happens.
As a special case, if an asynchronous method in fact does throw an exception (it typically shouldn’t), it is treated as if it returned a CompletionStage that is already completed exceptionally with the thrown exception.
@Asynchronous
A method that returns Future or CompletionStage may be annotated @Asynchronous.
Such method is executed on another thread.
Additionally, if the return type is CompletionStage, asynchronous fault tolerance applies.
|
Note that if an Asynchronous fault tolerance only applies if the |
Use @Asynchronous if the method has blocking logic, but you don’t want to block the caller thread.
For example:
@ApplicationScoped
public class MyService {
@Retry
@Asynchronous (1)
CompletionStage<String> hello() {
... blocking IO here ...
}
}
| 1 | Using the @Asynchronous annotation, because the method blocks, and it is necessary to offload its execution to another thread. |
@AsynchronousNonBlocking
| This is an additional feature of SmallRye Fault Tolerance and is not specified by MicroProfile Fault Tolerance. |
A method that returns CompletionStage may be annotated @AsynchronousNonBlocking.
In such case, the method is executed on the original thread, but asynchronous fault tolerance still applies.
Use @AsynchronousNonBlocking if the method does not have blocking logic, and you want the execution to stay on the caller thread.
For example:
@ApplicationScoped
public class MyService {
@Retry
@AsynchronousNonBlocking (1)
CompletionStage<String> hello() {
... non-blocking IO here ...
}
}
| 1 | Using the @AsynchronousNonBlocking annotation, because the method does not block and offloading execution to another thread is not necessary. |
Non-compatible mode
| This feature only works in the non-compatible mode. |
In the non-compatible mode, the @AsynchronousNonBlocking annotation is not necessary.
A method that returns CompletionStage and is not annotated @Asynchronous is automatically treated as @AsynchronousNonBlocking.
Links
For more information, see the Asynchronous Execution reference guide.