Skip to content

Commit

Permalink
Issue jakartaee#40 CompletionStage backed by ManagedExecutorService
Browse files Browse the repository at this point in the history
  • Loading branch information
njr-11 committed Mar 17, 2021
1 parent 8655b02 commit ddd05c8
Show file tree
Hide file tree
Showing 3 changed files with 251 additions and 14 deletions.
6 changes: 3 additions & 3 deletions api/pom.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2012, 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
Expand Down Expand Up @@ -247,8 +247,8 @@
<a href="{@docRoot}/doc-files/speclicense.html" target="_top">license terms</a>.
]]>
</bottom>
<docfilessubdirs>true</docfilessubdirs>

<docfilessubdirs>true</docfilessubdirs>
<source>1.8</source>
</configuration>
<executions>
<execution>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
* 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
Expand All @@ -16,7 +16,10 @@

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}.
Expand Down Expand Up @@ -162,10 +165,225 @@
* // Some account data...
* }
* </pre>
* <p>
*
*
* <p>ManagedExecutorService provides various methods which correspond to the
* static methods of {@link java.util.concurrent.CompletableFuture} and its
* constructor/<code>newIncompleteFuture</code> method,
* enabling you to create completion stages that are backed by the <code>ManagedExecutorService</code>
* 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.</p>
*
* <p>Example:</p>
* <pre>
* <code>ManagedExectorService executor = InitialContext.doLookup("java:comp/DefaultManagedExecutorService");
* ...
* CompletableFuture&lt;Integer&gt; future = executor
* .supplyAsync(supplier)
* .thenApply(function1)
* .thenApplyAsync(function2)
* ...
* </code>
* </pre>
*
* <p>Context propagation to completion stages that are backed by a
* <code>ManagedExecutorService</code> must be done in a consistent
* and predictable manner, which is defined as follows,</p>
*
* <ul>
* <li>
* If the supplied action is already contextual, (for example,
* <code>contextService.createContextualProxy(action, Runnable.class)</code>),
* then the action runs with the already-captured context.
* </li>
* <li>
* 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 <code>ManagedExecutorService</code> that is the default asynchronous execution facility
* for the new stage and its parent stage. In the case that a <code>ManagedExecutorService</code> is supplied
* as the <code>executor</code> argument to a <code>*Async</code> method, the supplied
* <code>ManagedExecutorService</code> is used to run the action, but not to determine the thread context
* propagation and clearing.
* </li>
* </ul>
*
* <p>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.</p>
*
* <p>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.</p>
*
* <p>Completion stages that are backed by a <code>ManagedExecutorService</code> must raise
* {@link java.lang.IllegalArgumentException} if supplied with an action that implements
* {@link ManagedTask}.</p>
*
* @since 1.0
*/
public interface ManagedExecutorService extends ExecutorService {
/**
* <p>Returns a new {@link java.util.concurrent.CompletableFuture}
* that is already completed with the specified value.</p>
*
* <p>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.</p>
*
* @param value result with which the completable future is completed.
* @param <U> result type of the completable future.
* @return the new completable future.
*/
<U> CompletableFuture<U> completedFuture(U value);

/**
* <p>Returns a new {@link java.util.concurrent.CompletionStage}
* that is already completed with the specified value.</p>
*
* <p>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.</p>
*
* @param value result with which the completion stage is completed.
* @param <U> result type of the completion stage.
* @return the new completion stage.
*/
<U> CompletionStage<U> completedStage(U value);

/**
* <p>
* Returns a new {@link java.util.concurrent.CompletableFuture}
* that is completed by the completion of the
* specified stage.
* </p>
*
* <p>
* The new completable future is backed by the <code>ManagedExecutorService</code> 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.
* </p>
*
* <p>
* When dependent stages are created from the new completable future, thread context is captured
* and/or cleared by the <code>ManagedExecutorService</code>. 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.
* </p>
*
* <p>
* Invocation of this method does not impact thread context propagation for the supplied
* completable future or any other dependent stages directly created from it.
* </p>
*
* @param <T> 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.
*/
<T> CompletableFuture<T> copy(CompletableFuture<T> stage);

/**
* <p>
* Returns a new {@link java.util.concurrent.CompletionStage}
* that is completed by the completion of the
* specified stage.
* </p>
*
* <p>
* The new completion stage is backed by the <code>ManagedExecutorService</code> 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.
* </p>
*
* <p>
* When dependent stages are created from the new completion stage, thread context is captured
* and/or cleared by the <code>ManagedExecutorService</code>. 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.
* </p>
*
* <p>
* Invocation of this method does not impact thread context propagation for the supplied
* stage or any other dependent stages directly created from it.
* </p>
*
* @param <T> 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.
*/
<T> CompletionStage<T> copy(CompletionStage<T> stage);

/**
* <p>Returns a new {@link java.util.concurrent.CompletableFuture}
* that is already exceptionally completed with the specified <code>Throwable</code>.</p>
*
* <p>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.</p>
*
* @param ex exception or error with which the completable future is completed.
* @param <U> result type of the completable future.
* @return the new completable future.
*/
<U> CompletableFuture<U> failedFuture(Throwable ex);

/**
* <p>Returns a new {@link java.util.concurrent.CompletionStage}
* that is already exceptionally completed with the specified <code>Throwable</code>.</p>
*
* <p>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.</p>
*
* @param ex exception or error with which the completion stage is completed.
* @param <U> result type of the completion stage.
* @return the new completion stage.
*/
<U> CompletionStage<U> failedStage(Throwable ex);

/**
* <p>Returns a new incomplete {@link java.util.concurrent.CompletableFuture}.</p>
*
* <p>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.</p>
*
* @param <U> result type of the completable future.
* @return the new completable future.
*/
<U> CompletableFuture<U> newIncompleteFuture();

/**
* <p>Returns a new {@link java.util.concurrent.CompletableFuture}
* that is completed by a task running in this executor
* after it runs the given action.</p>
*
* <p>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.</p>
*
* @param runnable the action to run before completing the returned completion stage.
* @return the new completable future.
*/
CompletableFuture<Void> runAsync(Runnable runnable);

/**
* <p>Returns a new {@link java.util.concurrent.CompletableFuture}
* that is completed by a task running in this executor
* after it runs the given action.</p>
*
* <p>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.</p>
*
* @param supplier an action returning the value to be used to complete the returned completion stage.
* @param <U> result type of the supplier and returned completable stage.
* @return the new completable future.
*/
<U> CompletableFuture<U> supplyAsync(Supplier<U> supplier);
}
35 changes: 27 additions & 8 deletions specification/src/main/asciidoc/jakarta-concurrency.adoc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
:sectnums:
= Jakarta Concurrency Specification, Version 2.0

Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2013, 2021 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.
Expand Down Expand Up @@ -194,6 +194,16 @@ as "tasks" will be referred to throughout the specification:
** `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()`

===== Optional Contextual Invocation Points

Expand All @@ -219,7 +229,9 @@ methods. These methods can be made contextual through the ContextService

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`). Tasks are units of
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
Expand All @@ -234,7 +246,8 @@ using CDI beans as tasks._
====

When a task instance is submitted to a managed instance of an
ExecutorService, the task becomes a contextual task. When the contextual
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.

Expand Down Expand Up @@ -352,7 +365,9 @@ component’s environment for the resource type. For example, all
`java:comp/env/concurrent` subcontext.

Components create task classes by implementing the `java.lang.Runnable` or
`java.util.concurrent.Callable` interfaces. These task classes are
`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
Expand All @@ -365,8 +380,10 @@ 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()`, or `invokeAny()`
methods. Task instances will run as an extension of the Jakarta EE
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.

Expand Down Expand Up @@ -1055,8 +1072,10 @@ typically stored with the Jakarta EE application component.

Task instances are submitted to a `ManagedScheduledExecutorService`
instance using any of the defined `submit()`, `execute()`, `invokeAll()`,
`invokeAny()`, `schedule()`, `scheduleAtFixedRate()` or
`scheduleWithFixedDelay()` methods. Task instances will run as an
`invokeAny()`, `runAsync()`, `supplyAsync()`, `schedule()`,
`scheduleAtFixedRate()`, or `scheduleWithFixedDelay()` methods.
Task instances can also be submitted to a `CompletionStage` that is
backed by a `ManagedScheduledExecutorService`. 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.
Expand Down

0 comments on commit ddd05c8

Please sign in to comment.