Concurrency Utilities for Java EE
Concurrency Utilities for Java EE is an asynchronous programming model that enables us to submit or schedule tasks to run in parallel, create threads that inherit Java EE context, and transfer Java EE context to invocation of interfaces such as asynchronous callbacks.
Concurrency Utilities for Java EE can improve performance by enabling a Java EE program to decompose operations into parallel tasks.
Tasks can run using the Java EE context of the submitting Java EE component. These tasks also can run with copies of other Java EE contexts, such as:
- Security context
- Internationalization context
- Work area context
Concurrency interfaces
Concurrency Utilities for Java EE provides four main types of resources, each of which can be configured and made available in JNDI:
- Managed executor service
- Applications use a managed executor to submit asynchronous tasks that can start running as threads, typically from a pool, when resources become available to run them. The tasks are instances of Callable or Runnable. The application is given a future, from which it can check status and obtain or await the result of task completion. The managed executor includes interfaces to submit and await completion of a group of tasks or of one task within a group. Tasks inherit the context of the thread that submits the task.
- Managed scheduled executor service
- Applications use a managed scheduled executor to schedule asynchronous tasks to start running after a specific point in time. The tasks are instances of Callable or Runnable. The managed scheduled executor includes interfaces for automatic rescheduling of a task, either at a fixed interval or computed according to custom business logic. Tasks inherit the context of the thread that schedules the task.
- Managed thread factory
- Applications use a managed thread factory to construct new threads that inherit the context of the application component that looked up or injected the managed thread factory.
- Context service
- Applications use a context service to construct contextual proxies, which allows invocations of one or more proxy interfaces to inherit the context of the thread that created the proxy.
Transactions
Every submitted or scheduled task, managed thread factory thread, and contextual proxy operation is called with any transaction that was previously on the thread suspended, much like container-managed transactions in typical enterprise beans. It is similar to the situation when an EJB method is called with TX_NOT_SUPPORTED. The run time starts a local transaction containment before invoking the method. The task can start its own global transaction if this transaction is possible for the calling Java EE component. We can override this behavior for contextual proxies by specifying the TRANSACTION execution property with a value of USE_TRANSACTION_OF_EXECUTION_THREAD. The property enables the transaction to remain on the thread of execution so that transactional operations performed within the proxy method can commit and roll back along with the transaction of the invoking thread.
When we call an entity bean from within a task, for example, we must have a global transactional context available on the current thread. Because tasks start local transactional contexts, we can encapsulate all entity bean logic in a session bean that has a method marked as TX_REQUIRES or equivalent. This process establishes a global transactional context from which we can access one or more entity bean methods.
Access to Java EE component metadata
If a task is a Java EE component, such as a session bean, its own metadata is active when a method is called. If a task is a simple Java object, the Java EE component metadata of the creating component is available to the bean. Like its submitting thread, the task can look up the java:comp, java:module, and java:app namespace. This look up enables the bean to access resource such as data sources, connection factories, and enterprise beans, just as it would if it were any other Java EE component. The environment properties of the creating component also are available to the task.
The java:comp namespace is identical to the one available for the creating component; the same restrictions apply. For example, if the enterprise bean or servlet has an EJB reference of java:comp/env/ejb/MyEJB, this EJB reference is available to the task.
Connection management
A task can use the data sources and connection factories that its creating Java EE component obtained using java:comp resource references. (For more information about resource references, refer to the References topic.) However, the bean method must access those connections using a get, use, or close pattern. There is no connection caching between method calls on an asynchronous task. The connection factories or data sources can be cached, but the connections must be retrieved on every method call, used, and then closed. While the task method can look up connection factories and data sources using a global JNDI name, this is not recommended for the following reasons:
- The JNDI name is hardcoded in the application (for example, as a property or string literal).
- The connection factories are not shared because there is no way to specify a sharing scope.
For code examples that demonstrate both the correct and the incorrect ways to access connections from tasks, refer to the Example: Concurrency connection management topic.
Deferred start of contextual tasks
Concurrency Utilities for Java EE supports deferred start by allowing serialization of Java EE thread context information. Contextual proxies are serializable if the instance supplied to the ContextService.createContextualProxy method is serializable. At this point, the context service creates a snapshot of the Java EE contexts enabled on the WorkManager. The resulting contextual proxy can then be serialized and stored in a database or file. This is useful when it is necessary to store Java EE service contexts, such as the current security identity or locale, and later inflate them and run some task within this context. All interface methods of the contextual proxy run with the previously captured thread context.
All contextual proxies must be deserialized by the same application that serialized it. All EJBs and classes must be present for Java to successfully inflate the objects contained within.
Deferred start and security
The security service context might require Common Secure Interoperability v2 (CSIv2) identity assertion to be enabled. Identity assertion is required when contextual proxy is deserialized and run to JAAS subject identity credential assignment. Review the following topics to better understand if we need to enable identity assertion, when using a contextual proxy:
- Configure Common Secure Interoperability v2 and Security Authentication Service authentication protocol
- Identity Assertion
There are also limitations with interoperating with contextual proxies across different versions of the product.
JPA-related limitations
Use of asynchronous tasks within a JPA extended persistence context is not supported.
A JPA extended persistence context is inconsistent with the scheduling and multi-threading capabilities of Concurrency Utilities for Java EE and will not be accessible from an asynchronous task.
Likewise, an asynchronous task must not take a javax.persistence.EntityManager (or subclass) as a parameter because EntityManager instances are not intended to be thread safe.
Subtopics
Related:
Callable and Runnable tasks Work managers References in application deployment descriptor files Local transaction containment Identity assertion to the downstream server Configure Common Secure Interoperability v2 (CSIV2) inbound and outbound communication settings