From 842fe132f1a3710c160e902c9e5087790bc81d20 Mon Sep 17 00:00:00 2001 From: Nathan Rauh Date: Thu, 18 Oct 2018 13:59:16 -0500 Subject: [PATCH] Issue #27 explicitly specify cleared=TRANSACTION --- .../concurrent/ManagedExecutorBuilder.java | 42 ++++++++++++-- .../concurrent/ManagedExecutorConfig.java | 39 +++++++++++-- .../concurrent/ThreadContext.java | 57 ++++++++++--------- .../concurrent/ThreadContextBuilder.java | 44 +++++++++++--- .../concurrent/ThreadContextConfig.java | 52 +++++++++++++---- .../concurrent/spi/ThreadContextProvider.java | 18 ++++-- 6 files changed, 191 insertions(+), 61 deletions(-) diff --git a/api/src/main/java/org/eclipse/microprofile/concurrent/ManagedExecutorBuilder.java b/api/src/main/java/org/eclipse/microprofile/concurrent/ManagedExecutorBuilder.java index 64118b4..3b16442 100644 --- a/api/src/main/java/org/eclipse/microprofile/concurrent/ManagedExecutorBuilder.java +++ b/api/src/main/java/org/eclipse/microprofile/concurrent/ManagedExecutorBuilder.java @@ -44,6 +44,9 @@ public interface ManagedExecutorBuilder { * instances.

* * @return new instance of ManagedExecutor. + * @throws IllegalArgumentException if the same thread context type is + * present in, or inferred by, both the {@link #cleared} set + * and the {@link #propagated} set. * @throws IllegalStateException if the direct or indirect * {@link org.eclipse.microprofile.concurrent.spi.ThreadContextProvider#getPrerequisites prerequisites} * of a ThreadContextProvider are unsatisfied, @@ -53,19 +56,48 @@ public interface ManagedExecutorBuilder { */ ManagedExecutor build(); + /** + *

Defines the set of thread context types to clear from the thread + * where the action or task executes. The previous context is resumed + * on the thread after the action or task ends.

+ * + *

This set replaces the cleared set that was previously + * specified on the builder instance, if any.

+ * + *

The default set of cleared thread context types is + * {@link ThreadContext#TRANSACTION}, which means that a transaction + * is not active on the thread when the action or task runs, such + * that each action or task is able to independently start and end + * its own transactional work.

+ * + *

Constants for specifying some of the core context types are provided + * on {@link ThreadContext}. Other thread context types must be defined + * by the specification that defines the context type or by a related + * MicroProfile specification.

+ * + *

Inclusion of a thread context type with prerequisites implies + * inclusion of the prerequisites, even if not explicitly specified.

+ * + * @param types types of thread context to clear from threads that run + * actions and tasks. + * @return the same builder instance upon which this method is invoked. + */ + ManagedExecutorBuilder cleared(String... types); + /** *

Defines the set of thread context types to capture from the thread * that creates a dependent stage (or that submits a task) and which to * propagate to the thread where the action or task executes.

* - *

This set replaces the set that was previously specified on the - * builder instance.

+ *

This set replaces the propagated set that was + * previously specified on the builder instance, if any.

* *

The default set of thread context types is - * {@link ThreadContext#DEFAULTS}, which includes all available + * {@link ThreadContext#ALL_OTHER}, which includes all available * thread context types that support capture and propagation to other - * threads, except for {@link ThreadContext#TRANSACTION} context, which - * is instead cleared (suspended) from the thread that runs the action or + * threads, except for those that are explicitly {@link cleared}, + * which, by default is {@link ThreadContext#TRANSACTION} context, + * in which case is suspended from the thread that runs the action or * task.

* *

Constants for specifying some of the core context types are provided diff --git a/api/src/main/java/org/eclipse/microprofile/concurrent/ManagedExecutorConfig.java b/api/src/main/java/org/eclipse/microprofile/concurrent/ManagedExecutorConfig.java index a9e522d..986cfb0 100644 --- a/api/src/main/java/org/eclipse/microprofile/concurrent/ManagedExecutorConfig.java +++ b/api/src/main/java/org/eclipse/microprofile/concurrent/ManagedExecutorConfig.java @@ -45,16 +45,42 @@ @Retention(RUNTIME) @Target(FIELD) public @interface ManagedExecutorConfig { + /** + *

Defines the set of thread context types to clear from the thread + * where the action or task executes. The previous context is resumed + * on the thread after the action or task ends.

+ * + *

By default, the transaction context is cleared/suspended from + * the execution thread so that actions and tasks can start and + * end transactions of their choosing, to independently perform their + * own transactional work, as needed.

+ * + *

Constants for specifying some of the core context types are provided + * on {@link ThreadContext}. Other thread context types must be defined + * by the specification that defines the context type or by a related + * MicroProfile specification.

+ * + *

Inclusion of a thread context type with prerequisites implies + * inclusion of the prerequisites, even if not explicitly specified.

+ * + *

A ManagedExecutor must fail to inject, raising + * DefinitionException on application startup, if the same + * context type is implicitly or explicitly included in this set + * as well as in the set specified by {@link #propagated}.

+ */ + String[] cleared() default { ThreadContext.TRANSACTION }; + /** *

Defines the set of thread context types to capture from the thread * that creates a dependent stage (or that submits a task) and which to * propagate to the thread where the action or task executes.

* *

The default set of thread context types is - * {@link ThreadContext#DEFAULTS}, which includes all available + * {@link ThreadContext#ALL_OTHER}, which includes all available * thread context types that support capture and propagation to other - * threads, except for {@link ThreadContext#TRANSACTION} context, which - * is instead cleared (suspended) from the thread that runs the action or + * threads, except for those that are explicitly {@link cleared}, + * which, by default is {@link ThreadContext#TRANSACTION} context, + * in which case is suspended from the thread that runs the action or * task.

* *

Constants for specifying some of the core context types are provided @@ -68,8 +94,13 @@ *

Thread context types which are not otherwise included in this set * are cleared from the thread of execution for the duration of the * action or task.

+ * + *

A ManagedExecutor must fail to inject, raising + * DefinitionException on application startup, if the same + * context type is implicitly or explicitly included in this set + * as well as in the set specified by {@link #cleared}.

*/ - String[] propagated() default { ThreadContext.DEFAULTS }; + String[] propagated() default { ThreadContext.ALL_OTHER }; /** *

Establishes an upper bound on the number of async completion stage diff --git a/api/src/main/java/org/eclipse/microprofile/concurrent/ThreadContext.java b/api/src/main/java/org/eclipse/microprofile/concurrent/ThreadContext.java index 2b20832..533ad69 100644 --- a/api/src/main/java/org/eclipse/microprofile/concurrent/ThreadContext.java +++ b/api/src/main/java/org/eclipse/microprofile/concurrent/ThreadContext.java @@ -48,17 +48,22 @@ */ public interface ThreadContext { /** - *

Identifier for all available thread context types that support - * capture and propagation to other threads.

+ *

Identifier for all available thread context types which are + * not specified individually under cleared, + * propagated, or unchanged.

* *

When using this constant, be aware that bringing in a new * context provider or updating levels of an existing context provider * might change the set of available thread context types.

- * + * + * @see ManagedExecutorBuilder#cleared + * @see ManagedExecutorBuilder#propagated + * @see ManagedExecutorConfig#cleared * @see ManagedExecutorConfig#propagated - * @see ThreadContextConfig#value + * @see ThreadContextBuilder + * @see ThreadContextConfig */ - static final String ALL = "All"; + static final String ALL_OTHER = "All other"; /** * Identifier for application context. Application context controls the @@ -68,7 +73,11 @@ public interface ThreadContext { * application context means that the thread is not associated with any * application. * + * @see ManagedExecutorBuilder#cleared + * @see ManagedExecutorBuilder#propagated + * @see ManagedExecutorConfig#cleared * @see ManagedExecutorConfig#propagated + * @see ThreadContextBuilder * @see ThreadContextConfig */ static final String APPLICATION = "Application"; @@ -79,36 +88,25 @@ public interface ThreadContext { * access to the scope of the session, request, and so forth that created the * contextualized action. * + * @see ManagedExecutorBuilder#cleared + * @see ManagedExecutorBuilder#propagated + * @see ManagedExecutorConfig#cleared * @see ManagedExecutorConfig#propagated + * @see ThreadContextBuilder * @see ThreadContextConfig */ static final String CDI = "CDI"; - /** - *

Identifier for the default set of thread context types, which is - * defined as all available thread context types that support capture and - * propagation to other threads except for {@link #TRANSACTION} context, - * which is instead cleared (suspended) from the thread that runs the - * action or task. This enables the action or task to choose whether, and - * if so, how, it participates in transactional work and is consistent - * with the generally established practice that transactions do not - * span threads.

- * - *

When using this constant, be aware that bringing in a new - * context provider or updating levels of an existing context provider - * might change the set of available thread context types.

- * - * @see ManagedExecutorConfig#propagated - * @see ThreadContextConfig - */ - static final String DEFAULTS = "Defaults"; - /** * Identifier for security context. Security context controls the credentials * that are associated with the thread. An empty/default security context * means that the thread is unauthenticated. * + * @see ManagedExecutorBuilder#cleared + * @see ManagedExecutorBuilder#propagated + * @see ManagedExecutorConfig#cleared * @see ManagedExecutorConfig#propagated + * @see ThreadContextBuilder * @see ThreadContextConfig */ static final String SECURITY = "Security"; @@ -118,15 +116,20 @@ public interface ThreadContext { * active transaction scope that is associated with the thread. * Implementations are not expected to propagate transaction context across * threads. Instead, the concept of transaction context is provided for its - * empty/default context, which means the active transaction on the thread + * cleared context, which means the active transaction on the thread * is suspended such that a new transaction can be started if so desired. * In most cases, the most desirable behavior will be to leave transaction - * context unconfigured such that it is defaulted to empty (suspended), + * context defaulted to cleared (suspended), * in order to prevent dependent actions and tasks from accidentally * enlisting in transactions that are on the threads where they happen to * run. * - * @see ThreadContextConfig#unchanged + * @see ManagedExecutorBuilder#cleared + * @see ManagedExecutorBuilder#propagated + * @see ManagedExecutorConfig#cleared + * @see ManagedExecutorConfig#propagated + * @see ThreadContextBuilder + * @see ThreadContextConfig */ static final String TRANSACTION = "Transaction"; diff --git a/api/src/main/java/org/eclipse/microprofile/concurrent/ThreadContextBuilder.java b/api/src/main/java/org/eclipse/microprofile/concurrent/ThreadContextBuilder.java index 260c4c9..e7e78e0 100644 --- a/api/src/main/java/org/eclipse/microprofile/concurrent/ThreadContextBuilder.java +++ b/api/src/main/java/org/eclipse/microprofile/concurrent/ThreadContextBuilder.java @@ -44,8 +44,9 @@ public interface ThreadContextBuilder { * * @return new instance of ThreadContext. * @throws IllegalArgumentException if the same thread context type is - * present in, or inferred by, both the {@link #propagated} set - * and the {@link #unchanged} set. + * present in, or inferred by, more than one of the + * following categories: + * ({@link #cleared}, {@link #propagated}, {@link #unchanged}). * @throws IllegalStateException if the direct or indirect * {@link org.eclipse.microprofile.concurrent.spi.ThreadContextProvider#getPrerequisites prerequisites} * of a ThreadContextProvider are unsatisfied, @@ -65,19 +66,48 @@ public static ThreadContextBuilder instance() { return ConcurrencyProvider.instance().newThreadContextBuilder(); } + /** + *

Defines the set of thread context types to clear from the thread + * where the action or task executes. The previous context is resumed + * on the thread after the action or task ends.

+ * + *

This set replaces the cleared set that was + * previously specified on the builder instance, if any.

+ * + *

The default set of cleared thread context types is + * {@link ThreadContext#TRANSACTION}, which means that a transaction + * is not active on the thread when the action or task runs, such + * that each action or task is able to independently start and end + * its own transactional work.

+ * + *

Constants for specifying some of the core context types are provided + * on {@link ThreadContext}. Other thread context types must be defined + * by the specification that defines the context type or by a related + * MicroProfile specification.

+ * + *

Inclusion of a thread context type with prerequisites implies + * inclusion of the prerequisites, even if not explicitly specified.

+ * + * @param types types of thread context to clear from threads that run + * actions and tasks. + * @return the same builder instance upon which this method is invoked. + */ + ThreadContextBuilder cleared(String... types); + /** *

Defines the set of thread context types to capture from the thread * that contextualizes an action or task. This context is later * re-established on the thread(s) where the action or task executes.

* - *

This set replaces the 'propagated' set that was previously specified - * on the builder instance.

+ *

This set replaces the propagated set that was + * previously specified on the builder instance, if any.

* *

The default set of thread context types is - * {@link ThreadContext#DEFAULTS}, which includes all available + * {@link ThreadContext#ALL_OTHER}, which includes all available * thread context types that support capture and propagation to other - * threads, except for {@link ThreadContext#TRANSACTION} context, which - * is instead cleared (suspended) from the thread that runs the action or + * threads, except for those that are explicitly {@link cleared}, + * which, by default is {@link ThreadContext#TRANSACTION} context, + * in which case is suspended from the thread that runs the action or * task.

* *

Constants for specifying some of the core context types are provided diff --git a/api/src/main/java/org/eclipse/microprofile/concurrent/ThreadContextConfig.java b/api/src/main/java/org/eclipse/microprofile/concurrent/ThreadContextConfig.java index 08dad61..4e2610e 100644 --- a/api/src/main/java/org/eclipse/microprofile/concurrent/ThreadContextConfig.java +++ b/api/src/main/java/org/eclipse/microprofile/concurrent/ThreadContextConfig.java @@ -45,16 +45,43 @@ @Retention(RUNTIME) @Target(FIELD) public @interface ThreadContextConfig { + /** + *

Defines the set of thread context types to clear from the thread + * where the action or task executes. The previous context is resumed + * on the thread after the action or task ends.

+ * + *

By default, the transaction context is cleared/suspended from + * the execution thread so that actions and tasks can start and + * end transactions of their choosing, to independently perform their + * own transactional work, as needed.

+ * + *

Constants for specifying some of the core context types are provided + * on {@link ThreadContext}. Other thread context types must be defined + * by the specification that defines the context type or by a related + * MicroProfile specification.

+ * + *

Inclusion of a thread context type with prerequisites implies + * inclusion of the prerequisites, even if not explicitly specified.

+ * + *

A ThreadContext must fail to inject, raising + * DefinitionException on application startup, if the same + * context type is implicitly or explicitly included in this set + * as well as in the set specified by {@link #propagated} + * or the set specified by {@link #unchanged}.

+ */ + String[] cleared() default { ThreadContext.TRANSACTION }; + /** *

Defines the set of thread context types to capture from the thread * that contextualizes an action or task. This context is later * re-established on the thread(s) where the action or task executes.

* *

The default set of thread context types is - * {@link ThreadContext#DEFAULTS}, which includes all available + * {@link ThreadContext#ALL_OTHER}, which includes all available * thread context types that support capture and propagation to other - * threads, except for {@link ThreadContext#TRANSACTION} context, which - * is instead cleared (suspended) from the thread that runs the action or + * threads, except for those that are explicitly {@link cleared}, + * which, by default is {@link ThreadContext#TRANSACTION} context, + * in which case is suspended from the thread that runs the action or * task.

* *

Constants for specifying some of the core context types are provided @@ -71,10 +98,10 @@ * *

A ThreadContext must fail to inject, raising * DefinitionException on application startup, if the same - * context type is included in this set as well as in the {@link #unchanged} - * set.

+ * context type is included in this set as well as in the {@link #cleared} + * set or the {@link #unchanged} set.

*/ - String[] value() default { ThreadContext.DEFAULTS }; + String[] value() default { ThreadContext.ALL_OTHER }; /** *

Defines a set of thread context types that are essentially ignored, @@ -90,8 +117,11 @@ * advanced patterns where it is desirable to leave certain context types * on the executing thread.

* - *

For example, to run under the transaction of the thread of execution:

- *
 @Inject @ThreadContextConfig(unchanged = ThreadContext.TRANSACTION)
+     * 

For example, to run as the current application, but under the + * transaction of the thread where the task executes:

+ *
 @Inject @ThreadContextConfig(unchanged = ThreadContext.TRANSACTION,
+     *                              propagated = ThreadContext.APPLICATION,
+     *                              cleared = ThreadContext.ALL_OTHER)
      * ThreadContext threadContext;
      * ...
      * task = threadContext.withCurrentContext(new MyTransactionalTask());
@@ -110,10 +140,8 @@
      * 

A ThreadContext must fail to inject, raising * DefinitionException on application startup, if the same * context type is included in this set as well as in the set specified by - * {@link ThreadContextConfig#value}, or if {@link ThreadContext#ALL} is - * included in the unchanged context because the latter would - * otherwise render the ThreadContext instance meaningless. - *

+ * {@link ThreadContextConfig#unchanged} or the set specified by + * {@link ThreadContextConfig#value}.

*/ String[] unchanged() default {}; } \ No newline at end of file diff --git a/api/src/main/java/org/eclipse/microprofile/concurrent/spi/ThreadContextProvider.java b/api/src/main/java/org/eclipse/microprofile/concurrent/spi/ThreadContextProvider.java index 1dc0ae3..8a752c0 100644 --- a/api/src/main/java/org/eclipse/microprofile/concurrent/spi/ThreadContextProvider.java +++ b/api/src/main/java/org/eclipse/microprofile/concurrent/spi/ThreadContextProvider.java @@ -18,6 +18,7 @@ */ package org.eclipse.microprofile.concurrent.spi; +import java.util.Collections; import java.util.Map; import java.util.Set; @@ -67,20 +68,20 @@ public interface ThreadContextProvider { ThreadContextSnapshot currentContext(Map props); /** - *

Returns empty/default context of the provided type. This context is not + *

Returns empty/cleared context of the provided type. This context is not * captured from the current thread, but instead represents the behavior that you * get for this context type when no particular context has been applied to the * thread.

* *

This is used in cases where the provided type of thread context should not be * propagated from the requesting thread or inherited from the thread of execution, - * in which case it is necessary to establish an empty/default context in its place, + * in which case it is necessary to establish an empty/cleared context in its place, * so that an action does not unintentionally inherit context of the thread that * happens to run it.

* - *

For example, a security context provider's empty/default context ensures there + *

For example, a security context provider's empty/cleared context ensures there * is no authenticated user on the thread. A transaction context provider's - * empty/default context ensures that any active transaction is suspended. + * empty/cleared context ensures that any active transaction is suspended. * And so forth.

* * @param props provided for compatibility with EE Concurrency spec, which allows @@ -88,7 +89,7 @@ public interface ThreadContextProvider { * that don't supply or use execution properties can ignore this parameter. * @return immutable empty/default context of the provided type. */ - ThreadContextSnapshot defaultContext(Map props); + ThreadContextSnapshot clearedContext(Map props); /** *

Returns an immutable set of thread context type identifiers (refer to @@ -105,11 +106,16 @@ public interface ThreadContextProvider { * for the duration of the contextualized action/task as well as during the initial * establishment and subsequent removal of thread context.

* + *

The default implementation of this method returns Collections.EMPTY_SET, + * indicating that this context type has no prerequisites.

+ * * @return immutable set of identifiers for prerequisite thread context types. * Thread context providers that have no prerequisites must return * Collections.EMPTY_SET to indicate this. */ - Set getPrerequisites(); + default Set getPrerequisites() { + return Collections.EMPTY_SET; + } /** *

Returns a human readable identifier for the type of thread context that is