All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jakarta.enterprise.concurrent.ManagedExecutorService Maven / Gradle / Ivy

/*
 * Copyright (c) 2010, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package jakarta.enterprise.concurrent;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutorService;
import java.util.function.Supplier;

/**
 * A manageable version of a {@link java.util.concurrent.ExecutorService}.
 * 

* A ManagedExecutorService extends the Java™ SE ExecutorService to provide * methods for submitting tasks for execution in a Jakarta™ EE environment. * Implementations of the ManagedExecutorService are * provided by a Jakarta EE Product Provider. Application Component Providers * use the Java Naming and Directory Interface™ (JNDI) to look-up instances of one * or more ManagedExecutorService objects using resource environment references. * ManagedExecutorService instances can also be injected into application * components through the use of the {@code Resource} annotation. *

* The Jakarta Concurrency specification describes several * behaviors that a ManagedExecutorService can implement. The Application * Component Provider and Deployer identify these requirements and map the * resource environment reference appropriately. *

* The most common uses for a ManagedExecutorService is to run short-duration asynchronous * tasks such as for processing of asynchronous methods in Jakarta * Enterprise Beans or for processing async tasks for Servlets that * supports asynchronous processing. *

* Tasks are run in managed threads provided by the Jakarta EE Product Provider * and are run within the application component context that submitted the task. * All tasks run without an explicit transaction (they do not enlist in the application * component's transaction). If a transaction is required, use a * {@code jakarta.transaction.UserTransaction} instance. A UserTransaction instance is * available in JNDI using the name: "java:comp/UserTransaction" or by * requesting an injection of a {@code jakarta.transaction.UserTransaction} object * using the {@code Resource} annotation. *

* Example: *

 * public run() {
 *   // Begin of task
 *   InitialContext ctx = new InitialContext();
 *   UserTransaction ut = (UserTransaction) ctx.lookup("java:comp/UserTransaction");
 *   ut.begin();
 *
 *   // Perform transactional business logic
 *
 *   ut.commit();
 * }
 * 
* * Tasks can optionally provide an {@link ManagedTaskListener} to receive * notifications of lifecycle events, through the use of {@link ManagedTask} * interface. *

* Example: *

 * public class MyRunnable implements Runnable, ManagedTask {
 *   ...
 *   public void run() {
 *     ...
 *   }
 *
 *   public ManagedTaskListener getManagedTaskListener() {
 *     return myManagedTaskListener;
 *   }
 *   ...
 * }
 *
 * MyRunnable task = ...;
 * ManagedExecutorService executor = ...;
 *
 * executor.submit(task); // lifecycle events will be notified to myManagedTaskListener
 * 
* * Asynchronous tasks are typically submitted to the ManagedExecutorService using one * of the {@code submit} methods, each of which return a {@link java.util.concurrent.Future} * instance. The {@code Future} represents the result of the task and can also be used to * check if the task is complete or wait for its completion. *

* * If the task is canceled, the result for the task is a * {@link java.util.concurrent.CancellationException} exception. If the task is unable * to run due to a reason other than cancellation, the result is a * {@link AbortedException} exception. *

* *Example: *

 * /**
 *  * Retrieve all accounts from several account databases in parallel.
 *  * Resource Mappings:
 *  *  type:      jakarta.enterprise.concurrent.ManagedExecutorService
 *  *  jndi-name: concurrent/ThreadPool
 *  */
 * public List<Account> getAccounts(long accountId) {
 *   try {
 *       javax.naming.InitialContext ctx = new InitialContext();
 *       ManagedExecutorService mes = (ManagedExecutorService)
 *           ctx.lookup("java:comp/env/concurrent/ThreadPool");
 *
 *       // Create a set of tasks to perform the account retrieval.
 *       ArrayList<Callable<Account>> retrieverTasks = new ArrayList<Callable<Account>>();
 *       retrieverTasks.add(new EISAccountRetriever());
 *       retrieverTasks.add(new RDBAccountRetriever());
 *
 *       // Submit the tasks to the thread pool and wait for them
 *       // to complete (successfully or otherwise).
 *       List<Future<Account>> taskResults= mes.invokeAll(retrieverTasks);
 *
 *       // Retrieve the results from the resulting Future list.
 *       ArrayList<Account> results = new ArrayList<Account>();
 *       for(Future<Account> taskResult : taskResults) {
 *           try {
 *               results.add(taskResult.get());
 *           } catch (ExecutionException e) {
 *               Throwable cause = e.getCause();
 *               // Handle the AccountRetrieverError.
 *           }
 *       }
 *
 *       return results;
 *
 *   } catch (NamingException e) {
 *       // Throw exception for fatal error.
 *   } catch (InterruptedException e) {
 *       // Throw exception for shutdown or other interrupt condition.
 *   }
 * }
 *
 *
 * public class EISAccountRetriever implements Callable<Account> {
 *     public Account call() {
 *         // Connect to our eis system and retrieve the info for the account.
 *         //...
 *         return null;
 *   }
 * }
 *
 * public class RDBAccountRetriever implements Callable<Account> {
 *     public Account call() {
 *         // Connect to our database and retrieve the info for the account.
 *         //...
 *   }
 * }
 *
 * public class Account {
 *     // Some account data...
 * }
 * 
* *

ManagedExecutorService provides various methods which correspond to the * static methods of {@link java.util.concurrent.CompletableFuture} and its * constructor/newIncompleteFuture method, * enabling you to create completion stages that are backed by the ManagedExecutorService * as the default asynchronous execution facility, both for those stages * as well as all dependent stages that are created from those, and so on. * This allows you to create pipelines of completion stage actions that run * with consistent and predictable thread context, regardless of which thread each * dependent action ends up running on.

* *

Example:

*
 * ManagedExectorService executor = InitialContext.doLookup("java:comp/DefaultManagedExecutorService");
 * ...
 * CompletableFuture<Integer> future = executor
 *    .supplyAsync(supplier)
 *    .thenApply(function1)
 *    .thenApplyAsync(function2)
 *    ...
 * 
 * 
* *

Context propagation to completion stages that are backed by a * ManagedExecutorService must be done in a consistent * and predictable manner, which is defined as follows,

* *
    *
  • * If the supplied action is already contextual, (for example, * contextService.createContextualProxy(action, Runnable.class)), * then the action runs with the already-captured context. *
  • *
  • * Otherwise, each type of thread context is either propagated from the thread * that creates the completion stage or the context is marked to be cleared, according to the * configuration of the ManagedExecutorService that is the default asynchronous execution facility * for the new stage and its parent stage. In the case that a ManagedExecutorService is supplied * as the executor argument to a *Async method, the supplied * ManagedExecutorService is used to run the action, but not to determine the thread context * propagation and clearing. *
  • *
* *

Each type of thread context is applied (either as cleared or previously captured) * to the thread that runs the action. The applied thread context is removed after the action * completes, whether successfully or exceptionally, restoring the thread's prior context.

* *

When dependent stages are created from the completion stage, and likewise from any dependent stages * created from those, and so on, thread context is captured or cleared in the same manner. * This guarantees that the action performed by each stage always runs under the thread context * of the code that creates the completion stage, unless the user explicitly overrides this by supplying a * pre-contextualized action.

* *

Completion stages that are backed by a ManagedExecutorService must raise * {@link java.lang.IllegalArgumentException} if supplied with an action that implements * {@link ManagedTask}.

* * @since 1.0 */ public interface ManagedExecutorService extends ExecutorService { /** *

Returns a new {@link java.util.concurrent.CompletableFuture} * that is already completed with the specified value.

* *

This executor is the default asynchronous execution facility for the new completion stage * that is returned by this method and all dependent stages that are created from it, * and all dependent stages that are created from those, as so forth.

* * @param value result with which the completable future is completed. * @param result type of the completable future. * @return the new completable future. * @since 3.0 */ CompletableFuture completedFuture(U value); /** *

Returns a new {@link java.util.concurrent.CompletionStage} * that is already completed with the specified value.

* *

This executor is the default asynchronous execution facility for the new completion stage * that is returned by this method and all dependent stages that are created from it, * and all dependent stages that are created from those, as so forth.

* * @param value result with which the completion stage is completed. * @param result type of the completion stage. * @return the new completion stage. * @since 3.0 */ CompletionStage completedStage(U value); /** *

* Returns a new {@link java.util.concurrent.CompletableFuture} * that is completed by the completion of the * specified stage. *

* *

* The new completable future is backed by the ManagedExecutorService upon which copy is invoked, * which serves as the default asynchronous execution facility * for the new stage and all dependent stages created from it, and so forth. *

* *

* When dependent stages are created from the new completable future, thread context is captured * and/or cleared by the ManagedExecutorService. This guarantees that the action * performed by each stage always runs under the thread context of the code that creates the stage, * unless the user explicitly overrides by supplying a pre-contextualized action. *

* *

* Invocation of this method does not impact thread context propagation for the supplied * completable future or any other dependent stages directly created from it. *

* * @param completable future result type. * @param stage a completable future whose completion triggers completion of the new completable * future that is created by this method. * @return the new completable future. * @since 3.0 */ CompletableFuture copy(CompletableFuture stage); /** *

* Returns a new {@link java.util.concurrent.CompletionStage} * that is completed by the completion of the * specified stage. *

* *

* The new completion stage is backed by the ManagedExecutorService upon which copy is invoked, * which serves as the default asynchronous execution facility * for the new stage and all dependent stages created from it, and so forth. *

* *

* When dependent stages are created from the new completion stage, thread context is captured * and/or cleared by the ManagedExecutorService. This guarantees that the action * performed by each stage always runs under the thread context of the code that creates the stage, * unless the user explicitly overrides by supplying a pre-contextualized action. *

* *

* Invocation of this method does not impact thread context propagation for the supplied * stage or any other dependent stages directly created from it. *

* * @param completion stage result type. * @param stage a completion stage whose completion triggers completion of the new stage * that is created by this method. * @return the new completion stage. * @since 3.0 */ CompletionStage copy(CompletionStage stage); /** *

Returns a new {@link java.util.concurrent.CompletableFuture} * that is already exceptionally completed with the specified Throwable.

* *

This executor is the default asynchronous execution facility for the new completion stage * that is returned by this method and all dependent stages that are created from it, * and all dependent stages that are created from those, as so forth.

* * @param ex exception or error with which the completable future is completed. * @param result type of the completable future. * @return the new completable future. * @since 3.0 */ CompletableFuture failedFuture(Throwable ex); /** *

Returns a new {@link java.util.concurrent.CompletionStage} * that is already exceptionally completed with the specified Throwable.

* *

This executor is the default asynchronous execution facility for the new completion stage * that is returned by this method and all dependent stages that are created from it, * and all dependent stages that are created from those, as so forth.

* * @param ex exception or error with which the completion stage is completed. * @param result type of the completion stage. * @return the new completion stage. * @since 3.0 */ CompletionStage failedStage(Throwable ex); /** * Returns a {@link ContextService} which has the same propagation settings as this ManagedExecutorService * and uses this ManagedExecutorService as the default asynchronous execution facility for * {@link java.util.concurrent.CompletionStage} and {@link java.util.concurrent.CompletableFuture} instances * that it creates via the withContextCapture methods. * * @return a ContextService with the same propagation settings * as this ManagedExecutorService. * @since 3.0 */ public ContextService getContextService(); /** *

Returns a new incomplete {@link java.util.concurrent.CompletableFuture}.

* *

This executor is the default asynchronous execution facility for the new completion stage * that is returned by this method and all dependent stages that are created from it, * and all dependent stages that are created from those, as so forth.

* * @param result type of the completable future. * @return the new completable future. * @since 3.0 */ CompletableFuture newIncompleteFuture(); /** *

Returns a new {@link java.util.concurrent.CompletableFuture} * that is completed by a task running in this executor * after it runs the given action.

* *

This executor is the default asynchronous execution facility for the new completion stage * that is returned by this method and all dependent stages that are created from it, * and all dependent stages that are created from those, as so forth.

* * @param runnable the action to run before completing the returned completion stage. * @return the new completable future. * @since 3.0 */ CompletableFuture runAsync(Runnable runnable); /** *

Returns a new {@link java.util.concurrent.CompletableFuture} * that is completed by a task running in this executor * after it runs the given action.

* *

This executor is the default asynchronous execution facility for the new completion stage * that is returned by this method and all dependent stages that are created from it, * and all dependent stages that are created from those, as so forth.

* * @param supplier an action returning the value to be used to complete the returned completion stage. * @param result type of the supplier and returned completable stage. * @return the new completable future. * @since 3.0 */ CompletableFuture supplyAsync(Supplier supplier); }