From c130ccbb958f747e41b52afce0e503797a68e641 Mon Sep 17 00:00:00 2001 From: Nathan Rauh Date: Wed, 27 Sep 2023 17:25:58 -0500 Subject: [PATCH 1/2] Issue #229 concurrency resources via @Inject and with qualifiers Signed-off-by: Nathan Rauh --- .../concurrent/ContextServiceDefinition.java | 41 +++++++++- .../concurrent/ManagedExecutorDefinition.java | 47 +++++++++++- .../ManagedScheduledExecutorDefinition.java | 43 ++++++++++- .../ManagedThreadFactoryDefinition.java | 45 +++++++++-- .../main/asciidoc/jakarta-concurrency.adoc | 75 +++++++++++++++++-- 5 files changed, 228 insertions(+), 23 deletions(-) diff --git a/api/src/main/java/jakarta/enterprise/concurrent/ContextServiceDefinition.java b/api/src/main/java/jakarta/enterprise/concurrent/ContextServiceDefinition.java index ab22ae5d..d1141b06 100644 --- a/api/src/main/java/jakarta/enterprise/concurrent/ContextServiceDefinition.java +++ b/api/src/main/java/jakarta/enterprise/concurrent/ContextServiceDefinition.java @@ -25,7 +25,10 @@ /** *

Defines a {@link ContextService} - * to be registered in JNDI by the container + * to be injected into + * {@link ContextService} injection points + * with the specified {@link #qualifiers()} + * and registered in JNDI by the container * under the JNDI name that is specified in the * {@link #name()} attribute.

* @@ -39,9 +42,19 @@ * unchanged = TRANSACTION, * cleared = ALL_REMAINING) * public class MyServlet extends HttpServlet { - * {@literal @}Resource(lookup = "java:app/concurrent/MyContext", + * {@literal @}Inject + * {@literal @}MyQualifier + * ConetxtService appContextSvc1; + * + * {@literal @}Resource(lookup = "java:app/concurrent/MyContext", * name = "java:app/concurrent/env/MyContextRef") - * ContextService appContextSvc; + * ContextService appContextSvc2; + * ... + * + * {@literal @}Qualifier + * {@literal @}Retention(RetentionPolicy.RUNTIME) + * {@literal @}Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE }) + * public {@literal @}interface MyQualifier {} * * *

Resource environment references in a deployment descriptor @@ -112,6 +125,28 @@ */ String name(); + /** + *

List of {@link Qualifier qualifier annotations}.

+ * + *

A {@link ContextService} injection point + * with these qualifier annotations injects a bean that is + * produced by this {@code ContextServiceDefinition}.

+ * + *

The default value is an empty list, indicating that this + * {@code ContextServiceDefinition} does not automatically produce + * bean instances for any injection points.

+ * + *

Applications can define their own {@link Producer Producers} + * for {@link ContextService} injection points as long as the + * qualifier annotations on the producer do not conflict with the + * non-empty {@link #qualifiers()} list of a + * {@code ContextServiceDefinition}.

+ * + * @return list of qualifiers. + * @since 3.1 + */ + Class[] qualifiers() default {}; + /** *

Types of context to clear whenever a thread runs the * contextual task or action. The thread's previous context diff --git a/api/src/main/java/jakarta/enterprise/concurrent/ManagedExecutorDefinition.java b/api/src/main/java/jakarta/enterprise/concurrent/ManagedExecutorDefinition.java index 5f479120..327d4971 100644 --- a/api/src/main/java/jakarta/enterprise/concurrent/ManagedExecutorDefinition.java +++ b/api/src/main/java/jakarta/enterprise/concurrent/ManagedExecutorDefinition.java @@ -23,9 +23,15 @@ import java.lang.annotation.Retention; import java.lang.annotation.Target; +import jakarta.enterprise.inject.spi.Producer; +import jakarta.inject.Qualifier; + /** *

Defines a {@link ManagedExecutorService} - * to be registered in JNDI by the container + * to be injected into + * {@link ManagedExecutorService} injection points + * with the specified {@link #qualifiers()} + * and registered in JNDI by the container * under the JNDI name that is specified in the * {@link #name()} attribute.

* @@ -36,16 +42,27 @@ *
  * {@literal @}ManagedExecutorDefinition(
  *     name = "java:module/concurrent/MyExecutor",
+ *     qualifiers = MyQualifier.class,
  *     context = "java:module/concurrent/MyExecutorContext",
  *     hungTaskThreshold = 120000,
  *     maxAsync = 5)
  * {@literal @}ContextServiceDefinition(
  *     name = "java:module/concurrent/MyExecutorContext",
  *     propagated = { SECURITY, APPLICATION })
- *  public class MyServlet extends HttpServlet {
- *    {@literal @}Resource(lookup = "java:module/concurrent/MyExecutor",
+ * public class MyServlet extends HttpServlet {
+ *     {@literal @}Inject
+ *     {@literal @}MyQualifier
+ *     ManagedExecutorService myExecutor1;
+ *
+ *     {@literal @}Resource(lookup = "java:module/concurrent/MyExecutor",
  *               name = "java:module/concurrent/env/MyExecutorRef")
- *     ManagedExecutorService myExecutor;
+ *     ManagedExecutorService myExecutor2;
+ *     ...
+ *
+ * {@literal @}Qualifier
+ * {@literal @}Retention(RetentionPolicy.RUNTIME)
+ * {@literal @}Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE })
+ * public {@literal @}interface MyQualifier {}
  * 
* *

Resource environment references in a deployment descriptor @@ -99,6 +116,28 @@ */ String name(); + /** + *

List of {@link Qualifier qualifier annotations}.

+ * + *

A {@link ManagedExecutorService} injection point + * with these qualifier annotations injects a bean that is + * produced by this {@code ManagedExecutorDefinition}.

+ * + *

The default value is an empty list, indicating that this + * {@code ManagedExecutorDefinition} does not automatically produce + * bean instances for any injection points.

+ * + *

Applications can define their own {@link Producer Producers} + * for {@link ManagedExecutorService} injection points as long as the + * qualifier annotations on the producer do not conflict with the + * non-empty {@link #qualifiers()} list of a + * {@code ManagedExecutorDefinition}.

+ * + * @return list of qualifiers. + * @since 3.1 + */ + Class[] qualifiers() default {}; + /** * The name of a {@link ContextService} instance which * determines how context is applied to tasks and actions that diff --git a/api/src/main/java/jakarta/enterprise/concurrent/ManagedScheduledExecutorDefinition.java b/api/src/main/java/jakarta/enterprise/concurrent/ManagedScheduledExecutorDefinition.java index bcf6fd02..f3c2b94e 100644 --- a/api/src/main/java/jakarta/enterprise/concurrent/ManagedScheduledExecutorDefinition.java +++ b/api/src/main/java/jakarta/enterprise/concurrent/ManagedScheduledExecutorDefinition.java @@ -25,7 +25,10 @@ /** *

Defines a {@link ManagedScheduledExecutorService} - * to be registered in JNDI by the container + * to be injected into + * {@link ManagedScheduledExecutorService} injection points + * with the specified {@link #qualifiers()} + * and registered in JNDI by the container * under the JNDI name that is specified in the * {@link #name()} attribute.

* @@ -42,10 +45,20 @@ * {@literal @}ContextServiceDefinition( * name = "java:comp/concurrent/MyScheduledExecutorContext", * propagated = APPLICATION) - * public class MyServlet extends HttpServlet { - * {@literal @}Resource(lookup = "java:comp/concurrent/MyScheduledExecutor", + * public class MyServlet extends HttpServlet { + * {@literal @}Inject + * {@literal @}MyQualifier + * ManagedScheduledExecutorService myScheduledExecutor1; + * + * {@literal @}Resource(lookup = "java:comp/concurrent/MyScheduledExecutor", * name = "java:comp/concurrent/env/MyScheduledExecutorRef") - * ManagedScheduledExecutorService myScheduledExecutor; + * ManagedScheduledExecutorService myScheduledExecutor2; + * ... + * + * {@literal @}Qualifier + * {@literal @}Retention(RetentionPolicy.RUNTIME) + * {@literal @}Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE }) + * public {@literal @}interface MyQualifier {} * * *

Resource environment references in a deployment descriptor @@ -99,6 +112,28 @@ */ String name(); + /** + *

List of {@link Qualifier qualifier annotations}.

+ * + *

A {@link ManagedScheduledExecutorService} injection point + * with these qualifier annotations injects a bean that is + * produced by this {@code ManagedScheduledExecutorDefinition}.

+ * + *

The default value is an empty list, indicating that this + * {@code ManagedScheduledExecutorDefinition} does not automatically produce + * bean instances for any injection points.

+ * + *

Applications can define their own {@link Producer Producers} + * for {@link ManagedScheduledExecutorService} injection points as long as the + * qualifier annotations on the producer do not conflict with the + * non-empty {@link #qualifiers()} list of a + * {@code ManagedScheduledExecutorDefinition}.

+ * + * @return list of qualifiers. + * @since 3.1 + */ + Class[] qualifiers() default {}; + /** * The name of a {@link ContextService} instance which * determines how context is applied to tasks and actions that diff --git a/api/src/main/java/jakarta/enterprise/concurrent/ManagedThreadFactoryDefinition.java b/api/src/main/java/jakarta/enterprise/concurrent/ManagedThreadFactoryDefinition.java index 6befe086..1a7b249c 100644 --- a/api/src/main/java/jakarta/enterprise/concurrent/ManagedThreadFactoryDefinition.java +++ b/api/src/main/java/jakarta/enterprise/concurrent/ManagedThreadFactoryDefinition.java @@ -24,8 +24,11 @@ import java.lang.annotation.Target; /** - *

Defines a {@link ManagedThreadFactory} - * to be registered in JNDI by the container + *

Defines {@link ManagedThreadFactory} instances + * to be injected into + * {@link ManagedThreadFactory} injection points + * with the specified {@link #qualifiers()} + * and registered in JNDI by the container * under the JNDI name that is specified in the * {@link #name()} attribute.

* @@ -41,10 +44,20 @@ * {@literal @}ContextServiceDefinition( * name = "java:global/concurrent/MyThreadFactoryContext", * propagated = APPLICATION) - * public class MyServlet extends HttpServlet { - * {@literal @}Resource(lookup = "java:global/concurrent/MyThreadFactory", + * public class MyServlet extends HttpServlet { + * {@literal @}Inject + * {@literal @}MyQualifier + * ManagedThreadFactory myThreadFactory1; + * + * {@literal @}Resource(lookup = "java:global/concurrent/MyThreadFactory", * name = "java:module/concurrent/env/MyThreadFactoryRef") - * ManagedThreadFactory myThreadFactory; + * ManagedThreadFactory myThreadFactory2; + * ... + * + * {@literal @}Qualifier + * {@literal @}Retention(RetentionPolicy.RUNTIME) + * {@literal @}Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE }) + * public {@literal @}interface MyQualifier {} * * *

Resource environment references in a deployment descriptor @@ -97,6 +110,28 @@ */ String name(); + /** + *

List of {@link Qualifier qualifier annotations}.

+ * + *

A {@link ManagedThreadFactory} injection point + * with these qualifier annotations injects a bean that is + * produced by this {@code ManagedThreadFactoryDefinition}.

+ * + *

The default value is an empty list, indicating that this + * {@code ManagedThreadFactoryDefinition} does not automatically produce + * bean instances for any injection points.

+ * + *

Applications can define their own {@link Producer Producers} + * for {@link ManagedThreadFactory} injection points as long as the + * qualifier annotations on the producer do not conflict with the + * non-empty {@link #qualifiers()} list of a + * {@code ManagedThreadFactoryDefinition}.

+ * + * @return list of qualifiers. + * @since 3.1 + */ + Class[] qualifiers() default {}; + /** * Determines how context is applied to threads from this * thread factory. diff --git a/specification/src/main/asciidoc/jakarta-concurrency.adoc b/specification/src/main/asciidoc/jakarta-concurrency.adoc index 0f9896ec..713e3b2b 100644 --- a/specification/src/main/asciidoc/jakarta-concurrency.adoc +++ b/specification/src/main/asciidoc/jakarta-concurrency.adoc @@ -1,7 +1,7 @@ :sectnums: -= Jakarta Concurrency Specification, Version 3.0 += Jakarta Concurrency Specification, Version 3.1 -Copyright (c) 2013, 2023 Oracle and/or its affiliates. All rights reserved. +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. @@ -58,6 +58,7 @@ 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 @@ -341,7 +342,16 @@ application components to run tasks asynchronously. Application Component Providers (application developers) (EE2.11.2) use a ManagedExecutorService instance and associated interfaces to develop application components that utilize the concurrency functions that these -interfaces provide. Instances for these objects are retrieved using the +interfaces provide. + +The application uses the +`jakarta.enterprise.concurrent.ManagedExecutorDefinition` annotation +to define instances of `ManagedExecutorService` and enumerate the +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). @@ -869,6 +879,12 @@ 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. + ==== System Administrator’s Responsibilities The System Administrator (EE.2.11.5) is responsible for monitoring and @@ -1042,7 +1058,16 @@ provides with the addition of `Trigger` and `ManagedTaskListener`. Application Component Providers (application developers) (EE2.11.2) use a `ManagedScheduledExecutorService` instance and associated interfaces to develop application components that utilize the concurrency functions -that these interfaces provide. Instances for these objects are retrieved +that these interfaces provide. + +The application uses the +`jakarta.enterprise.concurrent.ManagedScheduledExecutorDefinition` annotation +to define instances of `ManagedScheduledExecutorService` and enumerate the +qualifiers for `ManagedScheduledExecutorService` injection points +that are to receive a `ManagedScheduledExecutorService` bean +that is produced by the `ManagedScheduledExecutorDefinition`. + +Applications can also retrieve instances using the Java Naming and Directory Interface (JNDI) Naming Context (EE.5.2) or through injection of resource environment references (EE.5.8.1.1). @@ -1334,6 +1359,12 @@ types of contexts to be propagated by this default component must include naming context, class loader, and security information. +The Jakarta EE Product Provider must inject the default +`ManagedScheduledExecutorService` into injection points of +`ManagedScheduledExecutorService` that do not have any qualifiers +except for where the application provides the producer, +in which case the application's producer takes precedence. + ==== System Administrator’s Responsibilities The System Administrator (EE.2.110.5) is responsible for monitoring and @@ -1481,8 +1512,17 @@ provider's undefined thread context.). ==== Application Component Provider’s Responsibilities Application Component Providers (application developers) (EE2.11.2) use -a ContextService instance to create contextual object proxies. Instances -for these objects are retrieved using the Java Naming and Directory +a ContextService instance to create contextual object proxies. + +The application uses the +`jakarta.enterprise.concurrent.ContextServiceDefinition` annotation +to define instances of `ContextService` and enumerate the +qualifiers for `ContextService` injection points +that are to receive a `ContextService` bean +that is produced by the `ContextServiceDefinition`. + +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). @@ -1851,6 +1891,12 @@ by this default `ContextService` from a contextualizing application component must include naming context, class loader, and security information. +The Jakarta EE Product Provider must inject the default +`ContextService` into injection points of +`ContextService` that do not have any qualifiers +except for where the application provides the producer, +in which case the application's producer takes precedence. + ==== Transaction Management Contextual dynamic proxies support user-managed global transaction @@ -1928,7 +1974,16 @@ thread. Application Component Providers (application developers) (EE2.11.2) use a `jakarta.enterprise.concurrent.ManagedThreadFactory` instance to create -manageable threads. `ManagedThreadFactory` instances are retrieved using +manageable threads. + +The application uses the +`jakarta.enterprise.concurrent.ManagedThreadFactoryDefinition` annotation +to define instances of `ManagedThreadFactory` and enumerate the +qualifiers for `ManagedThreadFactory` injection points +that are to receive a `ManagedThreadFactory` bean +that is produced by the `ManagedThreadFactoryDefinition`. + +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). @@ -2237,6 +2292,12 @@ propagated by this default `ManagedThreadFactory` from a contextualizing application component must include naming context, class loader, and security information. +The Jakarta EE Product Provider must inject an instance of the +default `ManagedThreadFactory` into injection points of +`ManagedThreadFactory` that do not have any qualifiers +except for where the application provides the producer, +in which case the application's producer takes precedence. + ==== System Administrator’s Responsibilities The System Administrator (EE.2.11.5) is responsible for monitoring and From e743973a54e2a5f1354e9592824f398026b67c6d Mon Sep 17 00:00:00 2001 From: Nathan Rauh Date: Tue, 3 Oct 2023 16:54:16 -0500 Subject: [PATCH 2/2] fix copyright year --- specification/src/main/asciidoc/jakarta-concurrency.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/src/main/asciidoc/jakarta-concurrency.adoc b/specification/src/main/asciidoc/jakarta-concurrency.adoc index 713e3b2b..f93456a6 100644 --- a/specification/src/main/asciidoc/jakarta-concurrency.adoc +++ b/specification/src/main/asciidoc/jakarta-concurrency.adoc @@ -1,7 +1,7 @@ :sectnums: = Jakarta Concurrency Specification, Version 3.1 -Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved. +Copyright (c) 2013, 2023 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.