Specification: Jakarta Concurrency

Version: 3.1

Status: FINAL

Release: June 21, 2024

Copyright (c) 2018,2024 Eclipse Foundation.

Eclipse Foundation Specification License - v1.1

By using and/or copying this document, or the Eclipse Foundation document from which this statement is linked or incorporated by reference, you (the licensee) agree that you have read, understood, and will comply with the following terms and conditions:

Permission to copy, and distribute the contents of this document, or the Eclipse Foundation document from which this statement is linked, in any medium for any purpose and without fee or royalty is hereby granted, provided that you include the following on ALL copies of the document, or portions thereof, that you use:

  • link or URL to the original Eclipse Foundation document.

  • All existing copyright notices, or if one does not exist, a notice (hypertext is preferred, but a textual representation is permitted) of the form: "Copyright (c) [$date-of-document] Eclipse Foundation AISBL https://www.eclipse.org/legal/efsl.php "

Inclusion of the full text of this NOTICE must be provided. We request that authorship attribution be provided in any software, documents, or other items or products that you create pursuant to the implementation of the contents of this document, or any portion thereof.

No right to create modifications or derivatives of Eclipse Foundation documents is granted pursuant to this license, except anyone may prepare and distribute derivative works and portions of this document in software that implements the specification, in supporting materials accompanying such software, and in documentation of such software, PROVIDED that all such works include the notice below. HOWEVER, the publication of derivative works of this document for use as a technical specification is expressly prohibited.

The notice is:

"Copyright (c) 2018, 2024 Eclipse Foundation AISBL.This software or document includes material copied from or derived from Jakarta Concurrency and https://jakarta.ee/specifications/concurrency/3.0/."

Disclaimers

THIS DOCUMENT IS PROVIDED "AS IS," AND TO THE EXTENT PERMITTED BY APPLICABLE LAW THE COPYRIGHT HOLDERS AND THE ECLIPSE FOUNDATION AISBL MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF THE DOCUMENT ARE SUITABLE FOR ANY PURPOSE; NOR THAT THE IMPLEMENTATION OF SUCH CONTENTS WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.

TO THE EXTENT PERMITTED BY APPLICABLE LAW THE COPYRIGHT HOLDERS AND THE ECLIPSE FOUNDATION AISBL WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE DOCUMENT OR THE PERFORMANCE OR IMPLEMENTATION OF THE CONTENTS THEREOF.

The name and trademarks of the copyright holders or the Eclipse Foundation AISBL may NOT be used in advertising or publicity pertaining to this document or its contents without specific, written prior permission. Title to copyright in this document will at all times remain with copyright holders.

Jakarta Concurrency Specification, Version 3.1

Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.

1. Introduction

1.1. Overview

Jakarta™ Platform, Enterprise Edition (Jakarta EE) server containers such as the enterprise bean or web component container do not recommend using common Java SE concurrency APIs such as java.lang.Thread or java.util.Timer directly.

The server containers provide runtime support for Jakarta EE application components (such as Jakarta Servlets and Jakarta Enterprise Beans). They provide a layer between application component code and platform services and resources. All application component code is run on a thread managed by a container and each container typically expects all access to container-supplied objects to occur on the same thread.

It is because of this behavior that application components are typically unable to reliably use other Jakarta EE platform services from a thread that is not managed by the container.

Jakarta EE Product Providers (see chapter 2.12 of the Jakarta EE 11 Specification) also discourage the use of resources in a non-managed way, because it can potentially undermine the enterprise features that the platform is designed to provide such as availability, security, and reliability and scalability.

This specification provides a simple, standardized API for using concurrency from Jakarta EE application components without compromising the integrity of the container while still preserving the fundamental benefits of the Jakarta EE platform.

1.2. Goals of this specification

This specification was developed with the following goals in mind:

  • Utilize existing applicable Jakarta EE platform services. Provide a simple yet flexible API for application component providers to design applications using concurrency design principles.

  • Allow Java SE developers a simple migration path to the Jakarta EE platform by providing consistency between the Java SE and Jakarta EE platforms.

  • Allow application component providers to easily add concurrency to existing Jakarta EE applications.

  • Support simple (common) and advanced concurrency patterns without sacrificing usability.

1.3. Other Java Platform and Jakarta Specifications

The following Java Platform and Jakarta specifications are referenced in this document:

  • Concurrency Utilities Specification (JSR-166)

  • Jakarta Contexts and Dependency Injection

  • Jakarta Connectors

  • Java Platform Standard Edition

  • Jakarta Management

  • Java Naming and Directory Interface TM

  • Jakarta Transactions

  • Jakarta Transaction Service

  • JDBCTM API

  • Jakarta Messaging

  • Jakarta Enterprise Beans

1.4. Concurrency Utilities for Java EE Expert Group at the JCP

The original Java EE specification was the result of the collaborative work of the members of the Concurrency Utilities for Java EE Expert Group. The expert group includes the following members: Adam Bien, Marius Bogoevici (RedHat), Cyril Bouteille, Andrew Evers, Anthony Lai (Oracle), Doug Lea, David Lloyd (RedHat), Naresh Revanuru (Oracle), Fred Rowe (IBM Corporation), and Marina Vatkina (Oracle).

We would also like to thank former expert group members for their contribution to this specification, including Jarek Gawor (Apache Software Foundation), Chris D. Johnson (IBM Corporation), Billy Newport (IBM Corporation), Stephan Zachwiega (BEA Systems), Cameron Purdy (Tangosol), Gene Gleyzer (Tangosol), and Pierre VignJras.

1.5. Document Conventions

The regular Times font is used for information that is prescriptive to this specification.

The italic Times font is used for paragraphs that contain descriptive information, such as notes describing typical use, or notes clarifying the text with prescriptive specification.

The Courier font is used for code examples.

2. Overview

The focus of this specification is on providing asynchronous capabilities to Jakarta EE application components. This is largely achieved through extending the Concurrency Utilities API developed under JSR-166 and found in Java Platform, Standard Edition (Java SE) in the java.util.concurrent package.

The Java SE concurrency utilities provide an API that can be extended to support the majority of the goals defined in section 1.2. Application developers familiar with this API in the Java SE platform can leverage existing code libraries and usage patterns with little modification.

This specification has several aspects:

  • Definition and usage of centralized, manageable java.util.concurrent.ExecutorService objects in a Jakarta EE application server.

  • Usage of Java SE Concurrency Utilities in a Jakarta EE application.

  • Propagation of the Jakarta EE container’s runtime contextual information to other threads.

  • Managing and monitoring the lifecycle of asynchronous operations in a Jakarta EE Application Component.

  • Preserving application integrity.

2.1. Container-Managed vs. Unmanaged Threads

Jakarta EE application servers require resource management in order to centralize administration and protect application components from consuming unneeded resources. This can be achieved through the pooling of resources and managing a resource’s lifecycle. Using Java SE concurrency utilities such as the java.util.concurrent API, java.lang.Thread and java.util.Timer in a server application component such as a servlet or Jakarta Enterprise Bean are problematic since the container and server have no knowledge of these resources.

By extending the java.util.concurrent API, application servers and Jakarta EE containers can become aware of the resources that are used and provide the proper execution context for the asynchronous operations.

This is largely achieved by providing managed versions of the predominant java.util.concurrent.ExecutorService interfaces.

2.2. Application Integrity

Managed environments allow applications to coexist without causing harm to the overall system and isolate application components from one another. Administrators can adjust deployment and runtime settings to provide different qualities of service, provisioning of resources, scheduling of tasks, etc. Jakarta EE containers also provide runtime context services to the application component. When using concurrency utilities such as those in java.util.concurrent, these context services need to be available.

2.3. Container Thread Context

Jakarta EE depends on various context information to be available on the thread when interacting with other Jakarta EE services such as JDBC data sources, Jakarta Messaging providers and Jakarta Enterprise Beans. When using Jakarta EE services from a non-container thread, the following behaviors are required:

  • Saving the application component thread’s container context.

  • Identifying which container contexts to save and propagate.

  • Applying a container context to the current thread.

  • Restoring a thread’s original context.

The types of contexts to be propagated from a contextualizing application component include JNDI naming context, classloader, and security information. Containers must support propagation of these context types. In addition, containers can choose to support propagation of other types of context.

The relationships between the various Jakarta EE architectural elements, containers and concurrency constructs are shown in Figure 2‑1.

Containers (represented here in a single rectangle) provide environments for application components to safely interact with Jakarta EE Standard Services (represented in the rectangles directly below the Enterprise Bean/Web Container rectangle). Four new concurrency services (represented by four orange horizontal rectangles) allow application components and Jakarta EE Standard Services to run asynchronous tasks without violating container contracts.

The arrows in the diagram illustrate various flows from one part of the Jakarta EE platform to another.

image Figure 2‑1 Concurrency Utilities for Jakarta EE Architecture Diagram

2.3.1. Contextual Invocation Points

Container context and management constructs are propagated to component business logic at runtime using various invocation points on well-known interfaces. These invocation points or callback methods, hereby known as "tasks" will be referred to throughout the specification:

  • java.util.concurrent.Callable

    • call()

  • java.lang.Runnable

    • run()

  • java.util.function.BiConsumer

    • accept(T, U)

  • java.util.function.BiFunction

    • apply(T, U)

  • java.util.function.Consumer

    • accept(T)

  • java.util.function.Function

    • apply(T)

  • java.util.function.Supplier

    • get()

2.3.1.1. Flow Contextual Invocation Points

The java.util.concurrent.Flow class provides interfaces for establishing flow-controlled components. Container context and management constructs are also propagated to methods on the java.util.concurrent.Flow.Subscriber interface, including the inherited methods in java.util.concurrent.Flow.Processor.

2.3.1.2. Optional Contextual Invocation Points

The following callback methods run with unspecified context by default, but may be configured as contextual invocation points if desired:

  • jakarta.enterprise.concurrent.ManagedTaskListener

    • taskAborted()

    • taskSubmitted()

    • taskStarting()

  • jakarta.enterprise.concurrent.Trigger

    • getNextRunTime()

    • skipRun()

It is not required that container context be propagated to the threads that invoke these methods. This is to avoid the overhead of setting up the container context when it may not be needed in these callback methods. These methods can be made contextual through the ContextService (see following sections), which can make any Java object contextual.

2.3.2. Contextual Objects and Tasks

Tasks are concrete implementations of the Java SE java.util.concurrent.Callable and java.lang.Runnable interfaces (see the Javadoc for java.util.concurrent.ExecutorService) as well as the various functional interfaces that serve as completion stage actions (see the JavaDoc for java.util.concurrent.CompletionStage). Tasks are units of work that represent a computation or some business logic.

A contextual object is any Java object instance that has a particular application component’s thread context associated with it (for example, user identity).

Contextual Objects and Tasks referred here is not the same as the Context object as defined in the Jakarta Contexts and Dependency Injection specification. See section 2.3.2.1 on using CDI beans as tasks.

When a task instance is submitted to a managed instance of an ExecutorService or a managed CompletionStage, the task becomes a contextual task. When the contextual task runs, the task behaves as if it were still running in the container it was submitted with.

Contextual Task

Figure 2‑2 Contextual Task

2.3.2.1. Tasks and Jakarta Contexts and Dependency Injection (CDI)

CDI beans can be used as tasks. Such tasks could make use of injection if they are themselves components or are created dynamically using various CDI APIs. However, application developers should be aware of the following when using CDI beans as tasks:

  • Tasks that are submitted to a managed instance of ExecutorService may still be running after the lifecycle of the submitting component. Therefore, CDI beans with a scope of @RequestScoped, @SessionScoped, or @ConversationScoped are not recommended to use as tasks as it cannot be guaranteed that the tasks will complete before the CDI context is destroyed.

  • CDI beans with a scope of @ApplicationScoped or @Dependent can be used as tasks. However, it is still possible that the task could be running beyond the lifecycle of the submitting component, such as when the component is destroyed.

  • The transitive closure of CDI beans that are injected into tasks should follow the above guidelines regarding their scopes.

2.4. Usage with Jakarta Connectors

The Jakarta Connectors allows creating resource adapters that can plug into any compatible Jakarta EE application server. The Connectors specification provides a WorkManager interface that allows asynchronous processing for the resource adapter. It does not provide a mechanism for Jakarta EE applications to interact with an adapter’s WorkManager.

This specification addresses the need for Jakarta EE applications to run application business logic asynchronously using a jakarta.enterprise.concurrent.ManagedExecutorService or java.util.concurrent.ExecutorService with a jakarta.enterprise.concurrent.ManagedThreadFactory. It is the intent that Connectors jakarta.resource.work.WorkManager implementations may choose to utilize or wrap the java.util.concurrent.ExecutorService or other functionalities within this specification when appropriate.

Resource Adapters can access each of the Managed Objects described in the following sections by looking them up in the JNDI global namespace, through the JNDI context of the accessing application (see section 11.3.2 of the Jakarta Connectors specification).

2.5. Security

This specification largely defers most security decisions to the container and Jakarta EE Product Provider as defined in the Jakarta EE Specification.

If the container supports a security context, the Jakarta EE Product Provider must propagate that security context to the thread of execution.

Application Component Providers should use the interfaces provided in this specification when interacting with threads. If the Jakarta EE Product Provider has implemented a security manager, some operations may not be allowed.

3. Managed Objects

This section introduces four programming interfaces for Jakarta EE Product Providers to implement (see EE.2.12 for a detailed definition of each of the roles described here). Instances of these interfaces must be made available to application components through containers as managed objects:

  • Section 3.1, "ManagedExecutorService" –The interface for submitting asynchronous tasks from a container.

  • Section 3.2, "ManagedScheduledExecutorService" – The interface for scheduling tasks to run after a given delay or execute periodically.

  • Section 3.3, "ContextService" – The interface for creating contextual objects.

  • Section 3.4, "ManagedThreadFactory" – The interface for creating managed threads.

3.1. ManagedExecutorService

The jakarta.enterprise.concurrent.ManagedExecutorService is an interface that extends the java.util.concurrent.ExecutorService interface. Jakarta EE Product Providers provide implementations of this interface to allow application components to run tasks asynchronously.

3.1.1. Application Component Provider’s Responsibilities

Application Component Providers (application developers) (EE2.12.2) use a ManagedExecutorService instance and associated interfaces to develop application components that utilize the concurrency functions that these interfaces provide.

The application uses the jakarta.enterprise.concurrent.ManagedExecutorDefinition annotation to define instances of ManagedExecutorService and enumerate the required qualifiers for ManagedExecutorService injection points that are to receive a ManagedExecutorService bean that is produced by the ManagedExecutorDefinition.

Applications can also retrieve instances using the Java Naming and Directory Interface (JNDI) Naming Context (EE.5) or through injection of resource environment references (EE.5.8.1.1).

The Application Component Provider may use resource environment references to obtain references to a ManagedExecutorService instance as follows:

  • Assign an entry in the application component’s environment to the reference using the reference type of: jakarta.enterprise.concurrent.ManagedExecutorService. (See EE.5.8.1.3 for information on how resource environment references are declared in the deployment descriptor.)

  • Look up the managed object in the application component’s environment using JNDI (EE.5.2), or through resource injection by the use of the Resource annotation (EE.5.8.1.1).

This specification recommends, but does not require, that all resource environment references be organized in the appropriate subcontext of the component’s environment for the resource type. For example, all ManagedExecutorService references should be bound in the java:comp/env/concurrent subcontext.

Components create task classes by implementing the java.lang.Runnable or java.util.concurrent.Callable interfaces, or any of the functional interfaces that can be supplied to a java.util.concurrent.CompletionStage. These task classes are typically stored with the Jakarta EE application component.

Task classes can optionally implement the jakarta.enterprise.concurrent.ManagedTask interface to provide execution properties and to register a jakarta.enterprise.concurrent.ManagedTaskListener instance to receive lifecycle events notifications. Execution properties allow configuration and control of various aspects of the task including whether to suspend any current transaction on the thread and to provide identity information.

Task instances are submitted to a ManagedExecutorService instance using any of the defined submit(), execute(), invokeAll(), invokeAny(), runAsync(), or supplyAsync() methods. Task instances can also be submitted to a CompletionStage that is backed by a ManagedExecutorService. Task instances will run as an extension of the Jakarta EE container instance that submitted the task and may interact with Jakarta EE resources as defined in other sections of this specification.

It is important for Application Component Providers to identify and document the required behaviors and service-level agreements for each required ManagedExecutorService. The following example illustrates how the component can describe and utilize multiple executors.

3.1.1.1. Usage Example

In this example, an application component is performing two asynchronous operations from a servlet. One operation (reporter) is starting a task to generate a long running report. The other operations are short-running tasks that parallelize access to different back-end databases (builders).

Since each type of task has a completely different run profile, it makes sense to use two different ManagedExecutorService resource environment references. The attributes of each reference are documented using the <description> tag within the deployment descriptor of the application component and later mapped by the Deployer.

Reporter Task

The Reporter Task is a long-running task that communicates with a database to generate a report. The task is run asynchronously using a ManagedExecutorService. The client can then poll the server for the results.

Resource Environment Reference - Reporter Task

The following resource environment reference is added to the web.xml file for the web component. The description reflects the desired configuration attributes (see 3.1.4.1 ). Alternatively, the Resource annotation can be used in the Servlet code.

Using the description for documenting the configuration attributes of the managed object is optional. The format used here is only an example. Future revisions of Jakarta EE specifications may formalize usages such as this.

<resource-env-ref>
  <description>
    This executor is used for the application’s reporter task.
    This executor has the following requirements:
    Context Info: Local Namespace
  </description>
  <resource-env-ref-name>
    concurrent/LongRunningTasksExecutor
  </resource-env-ref-name>
  <resource-env-ref-type>
    jakarta.enterprise.concurrent.ManagedExecutorService
  </resource-env-ref-type>
</resource-env-ref>
Task Definition – Reporter Task

The task itself simply uses a resource-reference to a JDBC data source, and uses a connect/use/close pattern when invoking the data source.

public class ReporterTask implements Runnable {
  String reportName;

  public ReporterTask(String reportName) {
    this.reportName = reportName;
  }

public void run() {
  // Run the named report
  if("TransactionReport".equals(reportName)) {
    runTransactionReport();
  }
  else if("SummaryReport".equals(reportName)) {
    runSummaryReport();
  }
}

DataSource ds = ;

void runTransactionReport() {
  try (Connection con = ds.getConnection(); ...) {

    // Read/Write the data using our connection.
    ...
    // Commit.
    con.commit();
  }
}
Task Submission – Reporter Task

The task is started by an HTTP client connecting to a servlet. The client specifies the report name and other parameters to run. The handle to the task (the Future) is cached so that the client can query the results of the report. The Future will contain the results once the task has completed.

public class AppServlet extends HTTPServlet implements Servlet {

  // Cache our executor instance
  @Resource(name=concurrent/LongRunningTasksExecutor)
  ManagedExecutorService mes;

  protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    // Get the name of the report to run from the input params...
    // Assemble the header for the response.
    // Create a task instance
    ReporterTask reporterTask = new ReporterTask(reportName);

    // Submit the task to the ManagedExecutorService
    Future reportFuture = mes.submit(reporterTask);

    // Cache the future somewhere (like the client's session)
    // The client can then poll the servlet to determine
    // the status of the report.
    ...

    // Tell the user that the report has been submitted.
    ...
  }
}
Builder Tasks

This servlet accesses two different data sources and aggregates the results before returning the page contents to the user. Instead of accessing the data synchronously, it is instead done in parallel using two different tasks.

Resource Environment Reference – Builder Tasks

The following resource environment reference is added to the web.xml file for the web component. The description reflects the desired configuration attributes (see 3.1.4.1 ). Alternatively, the Resource annotation can be used in the Servlet code:

Using the description for documenting the configuration attributes of the managed object is optional. The format used here is only an example. Future revisions of Jakarta EE specifications may formalize usages such as this.

<resource-env-ref>
  <description>
    This executor is used for the application’s builder tasks.
    This executor has the following requirements:
    Context Info: Local Namespace, Security
  </description>
  <resource-env-ref-name>
    concurrent/BuilderExecutor
  </resource-env-ref-name>
  <resource-env-ref-type>
    jakarta.enterprise.concurrent.ManagedExecutorService
  </resource-env-ref-type>
</resource-env-ref>
Task Definition – Builder Tasks

The task itself simply uses some mechanism such as JDBC queries to retrieve the data from the persistent store. The task implements the jakarta.enterprise.concurrent.ManagedTask interface and supplies an identifiable name through the IDENTITY_NAME property to allow system administrators to diagnose problems.

public class AccountTask implements Callable<AccountInfo>, ManagedTask
{
  // The ID of the request to report on demand.
  String reqID;

  String accountID;
  Map<String, String> execProps;

  public AccountTask(String reqID, String accountID) {
    this.reqID=reqID;
    this.accountID=accountID;
    execProps = new HashMap<>();
    execProps.put(ManagedTask.IDENTITY_NAME, getIdentityName());
  }

  public AccountInfo call() {

    // Retrieve account info for the account from some persistent store
    AccountInfo info = ...;
    return info;
  }

  public String getIdentityName() {
    return "AccountTask: ReqID=" + reqID + ", Acct=" + accountID;
  }

  public Map<String, String> getExecutionProperties() {
    return execProps;
  }

  public ManagedTaskListener getManagedTaskListener() {
    return null;
  }
}

public class InsuranceTask implements Callable<InsuranceInfo>, ManagedTask {

  // The ID of the request to report on demand.
  String reqID

  String accountID;
  Map<String, String> execProps;

  public InsuranceTask (String reqID, String accountID) {
    this.reqID=reqID;
    this.accountID=accountID;
    execProps = new HashMap<>();

    execProps.put(ManagedTask.IDENTITY_NAME, getIdentityName());
  }

  public InsuranceInfo call() {
    // Retrieve the insurance info for the account from some persistent store
    InsuranceInfo info = ...;
    return info;
  }

  public String getIdentityName() {
    return "InsuranceTask: ReqID=" + reqID + ", Acct=" + accountID;
  }

  public Map<String, String> getExecutionProperties()
    return execProps;
  }

  public ManagedTaskListener getManagedTaskListener() {
    return null;
  }
}
Task Invocation – Builder Tasks

Tasks are created on demand by a request to the servlet from an HTTP client.

public class AppServlet extends HttpServlet implements Servlet {

  // Retrieve our executor instance.
  @Resource(name=concurrent/BuilderExecutor)
  ManagedExecutorService mes;

  protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // Get our arguments from the request (accountNumber and
    // requestID, in this case.
    // Assemble the header for the response.
    // Create and submit the task instances

    Future<AccountInfo> acctFuture = mes.submit(new AccountTask(reqID, accountID));

    Future<InsuranceInfo> insFuture = mes.submit (new InsuranceTask(reqID, accountID));

    // Wait for the results.
    AccountInfo accountInfo = acctFuture.get();
    InsuranceInfo insInfo = insFuture.get();

    // Process the results
  }
}

3.1.2. Application Assembler’s Responsibilities

The Application Assembler (EE.2.12.3) is responsible for assembling the application components into a complete Jakarta EE application and providing assembly instructions that describe the dependencies to the managed objects.

3.1.3. Deployer’s Responsibilities

The Deployer (EE.2.12.4) is responsible for deploying the application components into a specific operational environment. In the terms of this specification, the Deployer installs the application components and maps the dependencies defined by the Application Component Provider and Application Assembler to managed objects with the properly defined attributes. See EE.5.8.2 for details.

3.1.4. Jakarta EE Product Provider’s Responsibilities

The Jakarta EE Product Provider’s responsibilities are as defined in EE.5.8.3.

Jakarta EE Product Providers may include other contexts (e.g. Locale) that may be propagated to a task or a thread that invokes the callback methods in the jakarta.enterprise.concurrent.ManagedTaskListener interface. ManagedExecutorService implementations may add any additional contexts and provide the means for configuration of those contexts in any way so long as these contexts do not violate the required aspects of this specification.

The following section illustrates some possible configuration options that a Jakarta EE Product Provider may want to provide.

3.1.4.1. ManagedExecutorService Configuration Attributes

Each ManagedExecutorService may support one or more runtime behaviors as specified by configuration attributes. The Jakarta EE Product Provider will determine both the appropriate attributes and the means of configuring those attributes for their product.

3.1.4.2. Configuration Examples

This section and subsections illustrate some examples of how a Jakarta EE Product Provider could configure a ManagedExecutorService and the possible options that such a service could provide.

Providers may choose a more simplistic approach, or may choose to add more functionality, such as a higher quality-of-service, persistence, task partitioning or shared thread pools.

Each of the examples has the following attributes:

  • Name: An arbitrary name of the service for the deployer to use as a reference.

  • JNDI name: The arbitrary, but required, name to identify the service instance. The deployer uses this value to map the service to the component’s resource environment reference.

  • Context: A reference to a ContextService instance (see section 3.3). The context service can be used to define the context to propagate to the threads when running tasks. Having more than one ContextService, each with a different policy may be desirable for some implementations. If both Context and ThreadFactory attributes are specified, the Context attribute of the ThreadFactory configuration should be ignored.

  • ThreadFactory: A reference to a ManagedThreadFactory instance (see section 3.4). The ManagedThreadFactory instance can create threads with different attributes (such as priority).

  • Thread Use: If the application intends to run short vs. long-running tasks they can specify to use pooled or daemon threads.

  • Hung Task Threshold: The amount of time in milliseconds that a task can execute before it is considered hung.

  • Pool Info: If the executor is a thread pool, then the various thread pool attributes can be defined (this is based on the attributes for the Java java.util.concurrent.ThreadPoolExecutor class):

    •  Core Size: The number of threads to keep in the pool, even if they are idle.

    •  Maximum Size: The maximum number of threads to allow in the pool (could be unbounded).

    •  Keep Alive: The time to allow threads to remain idle when the number of threads is greater than the core size.

    •  Work Queue Capacity: The number of tasks that can be stored in the input bounded buffer (could be unbounded).

  • Reject Policy: The policy to use when a task is to be rejected by the executor. In this example, two policies are available:

    • Abort: Throw an exception when rejected.

    • Retry and Abort: Automatically resubmit to another instance and abort if it fails.

Typical Thread Pool

The Typical Thread Pool illustrates a common configuration for an application server with few applications. Each application expects to run a small number of short-duration tasks in the local process.

ManagedExecutorService

Name:

Typical Thread Pool

JNDI Name:

concurrent/execsvc/Shared

Context:

concurrent/ctx/AllContexts

Thread Factory:

concurrent/tf/normal

Hung Task Threshold

60000 ms

Pool Info:

Core Size: 5

Max Size: 25

Keep Alive: 5000 ms

Work Queue: 15

Capacity:

Reject Policy

  • Abort

  • Retry and Abort

##Table : Typical Thread Pool Configuration Example

Thread Pool for Long-Running Tasks

This executor describes a configuration in which the executor is used to run a few long-running tasks in the local process. In this example the task can run up to 24 hours before it is considered hung.

ManagedExecutorService

Name:

Long-Running Tasks Thread Pool

JNDI Name:

concurrent/execsvc/LongRunning

Context:

concurrent/ctx/AllContexts

Thread Factory:

concurrent/tf/longRunningThreadsFactory

Hung Task Threshold

24 hours

Pool Info:

Core Size: 0

Max Size: 5

Keep Alive: 1000 ms

Work Queue: 5

Capacity:

Reject Policy

  • Abort

  • Retry and Abort

##Table : Long-Running Tasks Thread Pool Configuration Example

OLTP Thread Pool

The OLTP (On-Line Transaction Processing) Thread Pool executor uses a thread pool with many more threads and a low hung-task threshold. It also uses a thread factory that creates threads with a slightly higher priority and a ContextService with a limited amount of context information.

ManagedExecutorService

Name:

Shared OLTP Thread Pool

JNDI Name:

concurrent/execsvc/OLTPShared

Context:

concurrent/ctx/OLTPContexts

Thread Factory:

concurrent/tf/oltp

Hung Task Threshold

20000 ms

Pool Info:

Core Size: 100

Max Size: 250

Keep Alive: 10000 ms

Work Queue: 100

Capacity:

Reject Policy

  • Abort

  • Retry and Abort

##Table : OLTP Thread Pool Configuration Example

3.1.4.3. Default ManagedExecutorService

The Jakarta EE Product Provider must provide a preconfigured, default ManagedExecutorService for use by application components under the JNDI name java:comp/DefaultManagedExecutorService. The types of contexts to be propagated by this default ManagedExecutorService from a contextualizing application component must include naming context, classloader, and security information.

The Jakarta EE Product Provider must inject the default ManagedExecutorService into injection points of ManagedExecutorService that do not have any qualifiers except for where the application provides the producer, in which case the application’s producer takes precedence.

3.1.5. System Administrator’s Responsibilities

The System Administrator (EE.2.12.5) is responsible for monitoring and overseeing the runtime environment. In the scope of this specification, these duties may include:

  • monitoring for hung tasks

  • monitoring resource usage (for example, threads and memory)

3.1.6. Lifecycle

The lifecycle of ManagedExecutorService instances are centrally managed by the application server and cannot be changed by an application.

A ManagedExecutorService instance is intended to be used by multiple components and applications. When the executor runs a task, the context of the thread is changed to match the component instance that submitted the task. The context is then restored when the task is complete.

In Figure 3‑1, a single ManagedExecutorService instance is used to run tasks (in blue) from multiple application components (each denoted in a different color). Each task, when submitted to the ManagedExecutorService automatically retains the context of the submitting component and it becomes a Contextual Task. When the ManagedExecutorService runs the task, the task would be run in the context of the submitting component (as noted by different colored boxes in the figure).