The Jakarta EE Product Provider runs the method on a ManagedExecutorService
and returns to the caller a CompletableFuture
that is backed by the same ManagedExecutorService
to represent the execution of the method. The ManagedExecutorService
is the default asynchronous execution facility for the CompletableFuture
and and all dependent stages that are created from those, and so on,
as defined by the ManagedExecutorService JavaDoc API.
The Jakarta EE Product Provider makes this CompletableFuture available
to the asynchronous method implementation via the
Asynchronous.Result.getFuture and
Asynchronous.Result.complete methods.
For example,
@Asynchronous
public CompletableFuture<Double> hoursWorked(LocalDate from, LocalDate to) {
// Application component's context is made available to the async method,
try (Connection con = ((DataSource) InitialContext.doLookup(
"java:comp/env/jdbc/timesheetDB")).getConnection()) {
...
return Asynchronous.Result.complete(total);
} catch (NamingException | SQLException x) {
throw new CompletionException(x);
}
}
with usage,
hoursWorked(mon, fri).thenAccept(total -> {
// Application component's context is made available to dependent stage actions,
DataSource ds = InitialContext.doLookup(
"java:comp/env/jdbc/payrollDB");
...
});
When the asynchronous method implementation returns a different
CompletableFuture instance, the Jakarta EE Product Provider
uses the completion of that instance to complete the CompletableFuture
that the Jakarta EE Product Provider returns to the caller,
completing it with the same result or exception.
For example,
@Asynchronous
public CompletableFuture<List<Itinerary>> findSingleLayoverFlights(Location source, Location dest) {
try {
ManagedExecutorService executor = InitialContext.doLookup(
"java:comp/DefaultManagedExecutorService");
return executor.supplyAsync(source::flightsFrom)
.thenCombine(executor.completedFuture(dest.flightsTo()),
Itinerary::sourceMatchingDest);
} catch (NamingException x) {
throw new CompletionException(x);
}
}
with usage,
findSingleLayoverFlights(RST, DEN).thenApply(Itinerary::sortByPrice);
Methods with the following return types can be annotated to be asynchronous methods:
The Jakarta EE Product Provider raises
UnsupportedOperationException
if other return types are used or if the annotation is placed at the class
level. The injection target of ElementType.TYPE is to be used only
by the CDI extension that is implemented by the Jakarta EE Product Provider to
register the asynchronous method interceptor. Applications must only use the
asynchronous method annotation at method level.
Exceptions that are raised by asynchronous methods are not raised directly
to the caller because the method runs asynchronously to the caller.
Instead, the CompletableFuture that represents the result
is completed with the raised exception. Asynchronous methods are
discouraged from raising checked exceptions because checked exceptions
force the caller to write exception handling code that is unreachable.
When a checked exception occurs, the asynchronous method implementation
can flow the exception back to the resulting CompletableFuture
either by raising a
CompletionException
with the original exception as the cause, or it can take the equivalent
approach of exceptionally completing the CompletableFuture, using
completeExceptionally
to supply the original exception as the cause.
Except where otherwise stated, the Jakarta EE Product Provider raises
RejectedExecutionException
upon invocation of the asynchronous method if evident upfront that it cannot
be accepted, for example if the JNDI name is not valid or points to something
other than a managed executor resource. If determined at a later point that the
asynchronous method cannot run (for example, if unable to establish thread context),
then the Jakarta EE Product Provider completes the CompletableFuture
exceptionally with CancellationException,
and chains a cause exception if there is any.
The Jakarta EE Product Provider must assign the interceptor for asynchronous methods
to have priority of Interceptor.Priority.PLATFORM_BEFORE + 5.
Interceptors with a lower priority, such as Transactional, must run on
the thread where the asynchronous method executes, rather than on the submitting thread.
When an asynchronous method is annotated as Transactional,
the transactional types which can be used are:
TxType.REQUIRES_NEW, which causes the method to run in a new transaction, and
TxType.NOT_SUPPORTED, which causes the method to run with no transaction.
All other transaction attributes must result in
UnsupportedOperationException
upon invocation of the asynchronous method.
| Modifier and Type | Class and Description |
|---|---|
| public static class | Asynchronous.Result
Mechanism by which the Jakarta EE Product Provider makes available
to the asynchronous method implementation the same
|
| Modifier and Type | Method and Description |
|---|---|
| public String | Returns: managed executor service JNDI name.JNDI name of a |
| executor | back to summary |
|---|---|
| public String executor() JNDI name of a
The default value is the JNDI name of the built-in
| |
CompletableFuture
instance that the Jakarta EE Product Provider supplies to the caller
of the asynchronous method.
Before invoking the asynchronous method implementation on a thread,
the Jakarta EE Product Provider invokes the setFuture method
which makes available to the asynchronous method implementation
the same CompletableFuture that the Jakarta EE Product Provider
returns to the caller.
The asynchronous method implementation invokes the getFuture method
to obtain the same CompletableFuture that the
Jakarta EE Product Provider returns to the caller.
The asynchronous method implementation can choose to complete
this future (normally or exceptionally) or otherwise arrange for its
completion, for example upon completion of a pipeline of completion stages.
Having this same CompletableFuture also enables the asynchronous
method implementation to determine if the caller has forcibly completed
(such as by cancellation or any other means) the CompletableFuture,
in which case the asynchronous method implementation could decide to end
immediately rather than continue processing.
For example,
@Asynchronous
public CompletableFuture<Double> hoursWorked(LocalDateTime from, LocalDateTime to) {
CompletableFuture<Double> future = Asynchronous.Result.getFuture();
if (future.isDone())
return future;
try (Connection con = ((DataSource) InitialContext.doLookup(
"java:comp/env/jdbc/timesheetDB")).getConnection()) {
...
for (ResultSet result = stmt.executeQuery(); result.next() && !future.isDone(); )
...
future.complete(total);
} catch (NamingException | SQLException x) {
future.completeExceptionally(x);
}
return future;
}
After the asynchronous method completes, the Jakarta EE Product Provider
invokes the setFuture method with a null value
to clear it from the thread.
| Modifier and Type | Field and Description |
|---|---|
| private static final ThreadLocal |
| Access | Constructor and Description |
|---|---|
| private |
| Modifier and Type | Method and Description |
|---|---|
| public static < type of result returned by the asynchronous method's T> CompletableFutureCompletableFuture. | Returns: the sameCompletableFuture that the container returns to the caller.result with which to complete the asynchronous method's result)CompletableFuture.Completes the |
| public static < type of result returned by the asynchronous method's T> CompletableFutureCompletableFuture. | Returns: the sameCompletableFuture that the container returns to the caller.Obtains the same |
| public static < type of result returned by the asynchronous method's T> voidCompletableFuture. | setFuture(final CompletableFuture<T>
CompletableFuture that the container returns to the caller,
or null to clear it.Before invoking the asynchronous method implementation on a thread,
the Jakarta EE Product Provider invokes this method to make available
to the asynchronous method implementation the same |
| FUTURES | back to summary |
|---|---|
| private static final ThreadLocal<CompletableFuture<?>> FUTURES | |
| Result | back to summary |
|---|---|
| private Result() | |
| complete | back to summary |
|---|---|
| public static <T> CompletableFuture Completes the This method must only be invoked by the asynchronous method implementation.
| |
| getFuture | back to summary |
|---|---|
| public static <T> CompletableFuture Obtains the same This method must only be invoked by the asynchronous method implementation.
| |
| setFuture | back to summary |
|---|---|
| public static <T> void setFuture(final CompletableFuture<T> future) Before invoking the asynchronous method implementation on a thread,
the Jakarta EE Product Provider invokes this method to make available
to the asynchronous method implementation the same
After the asynchronous method completes, the Jakarta EE Product Provider
invokes this method with a This method must only be invoked by the Jakarta EE Product Provider.
| |