Update documentation for using Jakarta Context Dependency and Injection instead of @Context for resource injection. Signed-off-by: James R. Perkins <jperkins@ibm.com>
diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/BeanParam.java b/jaxrs-api/src/main/java/jakarta/ws/rs/BeanParam.java index 68f44c6..064cbc3 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/BeanParam.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/BeanParam.java
@@ -30,10 +30,15 @@ * The annotation that may be used to inject custom JAX-RS "parameter aggregator" value object into a resource class * field, property or resource method parameter. * <p> - * The JAX-RS runtime will instantiate the object and inject all its fields and properties annotated with either one of - * the {@code @XxxParam} annotation ({@link PathParam @PathParam}, {@link FormParam @FormParam} ...) or the - * {@link jakarta.ws.rs.core.Context @Context} annotation. For the POJO classes same instantiation and injection rules - * apply as in case of instantiation and injection of request-scoped root resource classes. + * When running with an active CDI container, the bean is created and injected by CDI like any other CDI-managed + * type: fields and properties annotated with {@link jakarta.inject.Inject @Inject} are injected normally, and + * fields and properties annotated with one of the {@code @XxxParam} annotations ({@link PathParam @PathParam}, + * {@link FormParam @FormParam} ...) are resolved from the current request context using the same CDI qualifier + * mechanism used for resource method parameters. + * <p> + * Without an active CDI container, the JAX-RS runtime instantiates the object and injects all its fields and + * properties annotated with one of the {@code @XxxParam} annotations. For the POJO classes the same instantiation + * and injection rules apply as in the case of instantiation and injection of request-scoped root resource classes. * </p> * For example: *
diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/container/ResourceContext.java b/jaxrs-api/src/main/java/jakarta/ws/rs/container/ResourceContext.java index 0cd23fe..577878d 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/container/ResourceContext.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/container/ResourceContext.java
@@ -16,12 +16,10 @@ package jakarta.ws.rs.container; -import jakarta.ws.rs.core.Context; - /** * The resource context provides access to instances of resource classes. * <p> - * This interface can be injected using the {@link Context} annotation. + * This interface can be injected using the {@link jakarta.inject.Inject Inject} annotation. * </p> * <p> * The resource context can be utilized when instances of managed resource classes are to be returned by sub-resource
diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/core/Application.java b/jaxrs-api/src/main/java/jakarta/ws/rs/core/Application.java index 6e4ea70..4d69bcd 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/core/Application.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/core/Application.java
@@ -25,7 +25,7 @@ * implementation supplies a concrete subclass of this abstract class. * <p> * The implementation-created instance of an Application subclass may be injected into resource classes and providers - * using {@link jakarta.ws.rs.core.Context}. + * using {@link jakarta.inject.Inject}. * </p> * <p> * In case any of the {@code Application} subclass methods or its constructor throws a {@link RuntimeException}, the
diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/core/Configurable.java b/jaxrs-api/src/main/java/jakarta/ws/rs/core/Configurable.java index df9bba7..f05912f 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/core/Configurable.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/core/Configurable.java
@@ -261,7 +261,7 @@ * As opposed to components registered via {@link #register(Class)} method, the lifecycle of providers registered using * this instance-based {@code register(...)} is not managed by JAX-RS runtime. The same registered component instance is * used during the whole lifespan of the configurable context. Fields and properties of all registered JAX-RS component - * instances are injected with their declared dependencies (see {@link Context}) by the JAX-RS runtime prior to use. + * instances are injected with their declared dependencies by the Jakarta REST runtime prior to use. * </p> * * @param component JAX-RS component instance to be configured in the scope of this configurable context.
diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/core/Configuration.java b/jaxrs-api/src/main/java/jakarta/ws/rs/core/Configuration.java index 54a91ae..069f562 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/core/Configuration.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/core/Configuration.java
@@ -32,7 +32,7 @@ * component classes and/or instances. * </p> * <p> - * This interface can be injected using the {@link Context} annotation. + * This interface can be injected using the {@link jakarta.inject.Inject} annotation. * </p> * * @author Marek Potociar @@ -174,7 +174,7 @@ /** * Get the immutable set of registered JAX-RS component (such as provider or {@link Feature feature}) instances to be * utilized by the configurable instance. Fields and properties of returned instances are injected with their declared - * dependencies (see {@link Context}) by the runtime prior to use. + * dependencies by the runtime prior to use. * <p> * For each component type, there can be only a single class-based or instance-based registration present in the * configuration context at any given time.
diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/core/HttpHeaders.java b/jaxrs-api/src/main/java/jakarta/ws/rs/core/HttpHeaders.java index 1f27f82..e20a231 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/core/HttpHeaders.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/core/HttpHeaders.java
@@ -28,7 +28,6 @@ * * @author Paul Sandoz * @author Marc Hadley - * @see Context * @since 1.0 */ public interface HttpHeaders {
diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/core/SecurityContext.java b/jaxrs-api/src/main/java/jakarta/ws/rs/core/SecurityContext.java index aeabef6..c582e6f 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/core/SecurityContext.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/core/SecurityContext.java
@@ -23,7 +23,6 @@ * * @author Paul Sandoz * @author Marc Hadley - * @see Context * @since 1.0 */ public interface SecurityContext {
diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/core/UriInfo.java b/jaxrs-api/src/main/java/jakarta/ws/rs/core/UriInfo.java index 2fad294..2d6b2ef 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/core/UriInfo.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/core/UriInfo.java
@@ -32,7 +32,6 @@ * * @author Paul Sandoz * @author Marc Hadley - * @see Context * @since 1.0 */ public interface UriInfo {
diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/ext/Providers.java b/jaxrs-api/src/main/java/jakarta/ws/rs/ext/Providers.java index ff518b5..e404526 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/ext/Providers.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/ext/Providers.java
@@ -26,7 +26,6 @@ * * @author Paul Sandoz * @author Marc Hadley - * @see jakarta.ws.rs.core.Context * @see MessageBodyReader * @see MessageBodyWriter * @see ContextResolver
diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/sse/SseEventSink.java b/jaxrs-api/src/main/java/jakarta/ws/rs/sse/SseEventSink.java index b245435..5101501 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/sse/SseEventSink.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/sse/SseEventSink.java
@@ -28,7 +28,7 @@ * @GET * @Path("eventStream") * @Produces(MediaType.SERVER_SENT_EVENTS) - * public void eventStream(@Context SseEventSink eventSink) { + * public void eventStream(SseEventSink eventSink) { * // ... * } * </pre>
diff --git a/jaxrs-spec/src/main/asciidoc/chapters/appendix/_bibliography.adoc b/jaxrs-spec/src/main/asciidoc/chapters/appendix/_bibliography.adoc index 4248312..b1446a9 100644 --- a/jaxrs-spec/src/main/asciidoc/chapters/appendix/_bibliography.adoc +++ b/jaxrs-spec/src/main/asciidoc/chapters/appendix/_bibliography.adoc
@@ -47,8 +47,8 @@ - [[[bib13,13]]] Jakarta^®^ Concurrency Specification, Version 2.0. Available at: https://jakarta.ee/specifications/concurrency/2.0/ -- [[[bib14,14]]] Jakarta^®^ Contexts and Dependency Injection Specification, Version 2.0. Available at: - https://jakarta.ee/specifications/cdi/2.0/ +- [[[bib14,14]]] Jakarta^®^ Contexts and Dependency Injection Specification, Version 5.0. Available at: + https://jakarta.ee/specifications/cdi/5.0/ - [[[bib15,15]]] Jakarta^®^ Annotations Specification, Version 2.0. Available at: https://jakarta.ee/specifications/annotations/2.0/
diff --git a/jaxrs-spec/src/main/asciidoc/chapters/appendix/_changes-since-4.0-release.adoc b/jaxrs-spec/src/main/asciidoc/chapters/appendix/_changes-since-4.0-release.adoc index ed3c003..4f30a6a 100644 --- a/jaxrs-spec/src/main/asciidoc/chapters/appendix/_changes-since-4.0-release.adoc +++ b/jaxrs-spec/src/main/asciidoc/chapters/appendix/_changes-since-4.0-release.adoc
@@ -12,3 +12,25 @@ === Changes Since 4.0 Release * <<standard_entity_providers>>: Added entity provider for `java.nio.file.Path` +* <<cdi>>: Required CDI 5.0 or later for proper integration of Jakarta REST and CDI injection (https://github.com/jakartaee/rest/issues/569[#569]) +* <<cdi-injection-model>>: Documented comprehensive CDI injection model for resources and providers (https://github.com/jakartaee/rest/issues/569[#569]) +* <<cdi>>: Updated `@ApplicationPath`, `@Path`, and `@Provider` annotations to be CDI stereotype +annotations with default scopes (`@ApplicationScoped` for `@ApplicationPath` and `@Provider`, +`@RequestScoped` for `@Path`) (https://github.com/jakartaee/rest/issues/556[#556], https://github.com/jakartaee/rest/issues/952[#952]) +* <<cdi-injection-model>>: Parameter extraction annotations (`@QueryParam`, `@PathParam`, +`@HeaderParam`, `@MatrixParam`, `@CookieParam`, `@FormParam`) now act as CDI qualifiers (https://github.com/jakartaee/rest/issues/569[#569]) +* <<cdi-injection-model>>: Fields in CDI-managed beans must use `@Inject` instead of the +deprecated `@Context` annotation (https://github.com/jakartaee/rest/issues/569[#569], https://github.com/jakartaee/rest/issues/1209[#1209]) +* <<cdi-injection-model>>: Resource method parameters support only Jakarta REST context types, +parameter extraction annotations, entity parameters, `AsyncResponse`, and `SseEventSink`; +arbitrary CDI beans must be injected via fields or constructors (https://github.com/jakartaee/rest/issues/569[#569]) +* <<cdi-injection-model>>: Clarified that `AsyncResponse` and `SseEventSink` can only be +used as resource method parameters, not as injectable fields (https://github.com/jakartaee/rest/issues/569[#569]) +* <<cdi-producers>>: Required CDI producers for Jakarta REST context types and parameter +extraction annotations (https://github.com/jakartaee/rest/issues/569[#569]) +* Deprecated `@Context` annotation for removal in a future release (https://github.com/jakartaee/rest/issues/569[#569], https://github.com/jakartaee/rest/issues/1209[#1209]) +* Deprecated `@Suspended` annotation in 5.0 for removal in a future release; use type-alone approach +for `AsyncResponse` in CDI environments (https://github.com/jakartaee/rest/issues/1209[#1209]) +* <<servlet_container>>: Deprecated `@Context` injection for Servlet-defined types; use CDI +injection (`@Inject`) as specified by Jakarta Servlet and Jakarta EE Platform specifications (https://github.com/jakartaee/rest/issues/1214[#1214]) +* Scoped Additional Requirements section to non-CDI environments; CDI specification defines bean lifecycle behaviors for CDI-managed beans (https://github.com/jakartaee/rest/issues/1215[#1215])
diff --git a/jaxrs-spec/src/main/asciidoc/chapters/context/_contexttypes.adoc b/jaxrs-spec/src/main/asciidoc/chapters/context/_contexttypes.adoc index 13a1a05..3d76bda 100644 --- a/jaxrs-spec/src/main/asciidoc/chapters/context/_contexttypes.adoc +++ b/jaxrs-spec/src/main/asciidoc/chapters/context/_contexttypes.adoc
@@ -17,12 +17,27 @@ which are injectable in both client and server-side providers, all the other types are server-side only. +[NOTE] +==== +In CDI-enabled environments, these context types MUST be made available +for injection via CDI producers as specified in <<cdi-producers>>. The +use of `@Context` annotation is deprecated in favor of CDI injection using +`@Inject` (for fields and constructors) or type-based injection (for +resource method parameters). See <<cdi-injection-model>> for details on +the CDI injection model for Jakarta REST. + +For `Client` instances and `SeBootstrap`-based deployments, `@Inject` for +`Configuration` and `Providers` MUST be supported when CDI is available. +Where no CDI container is present, the deprecated `@Context` annotation +remains fully supported for these types. +==== + [[application]] ==== Application The instance of the application-supplied `Application` subclass can be -injected into a class field or method parameter using the -`@Context` annotation. Access to the `Application` subclass instance +injected into a class field using the `@Inject` annotation or as a resource +method parameter. Access to the `Application` subclass instance allows configuration information to be centralized in that class. Note that this cannot be injected into the `Application` subclass itself since this would create a circular dependency. @@ -30,9 +45,9 @@ [[uris-and-uri-templates]] ==== URIs and URI Templates -An instance of `UriInfo` can be injected into a class field or method -parameter using the `@Context` annotation. `UriInfo` provides both -static and dynamic, per-request information, about the components of a +An instance of `UriInfo` can be injected into a class field using the +`@Inject` annotation or as a resource method parameter. +`UriInfo` provides both static and dynamic, per-request information, about the components of a request URI. E.g. the following would return the names of any query parameters in a request: @@ -40,11 +55,29 @@ ---- @GET @Produces("text/plain") -public String listQueryParamNames(@Context UriInfo info) { +public String listQueryParamNames(UriInfo info) { StringBuilder buf = new StringBuilder(); for (String param: info.getQueryParameters().keySet()) { buf.append(param); - buf.append("\n"); + buf.append('\n'); + } + return buf.toString(); +} +---- + +[source,java] +---- + +@Inject +UriInfo info; + +@GET +@Produces("text/plain") +public String listQueryParamNames() { + StringBuilder buf = new StringBuilder(); + for (String param: info.getQueryParameters().keySet()) { + buf.append(param); + buf.append('\n'); } return buf.toString(); } @@ -56,8 +89,8 @@ [[httpheaders]] ==== Headers -An instance of `HttpHeaders` can be injected into a class field or -method parameter using the `@Context` annotation. `HttpHeaders` provides +An instance of `HttpHeaders` can be injected into a class field using the +`@Inject` annotation or as a resource method parameter. `HttpHeaders` provides access to request header information either in map form or via strongly typed convenience methods. E.g. the following would return the names of all the headers in a request: @@ -66,11 +99,28 @@ ---- @GET @Produces("text/plain") -public String listHeaderNames(@Context HttpHeaders headers) { +public String listHeaderNames(HttpHeaders headers) { StringBuilder buf = new StringBuilder(); for (String header: headers.getRequestHeaders().keySet()) { buf.append(header); - buf.append("\n"); + buf.append('\n'); + } + return buf.toString(); +} +---- + +[source,java] +---- +@Inject +HttpHeaders headers; + +@GET +@Produces("text/plain") +public String listHeaderNames() { + StringBuilder buf = new StringBuilder(); + for (String header: headers.getRequestHeaders().keySet()) { + buf.append(header); + buf.append('\n'); } return buf.toString(); } @@ -86,8 +136,9 @@ ==== Content Negotiation and Preconditions JAX-RS simplifies support for content negotiation and preconditions -using the `Request` interface. An instance of `Request` can be injected -into a class field or method parameter using the `@Context` annotation. +using the `Request` interface. An instance of `Request` can be injected +into a class field using the `@Inject` annotation or as a resource method +parameter. The methods of `Request` allow a caller to determine the best matching representation variant and to evaluate whether the current state of the resource matches any preconditions in the request. Precondition support @@ -99,7 +150,23 @@ [source,java] ---- @PUT -public Response updateFoo(@Context Request request, Foo foo) { +public Response updateFoo(Request request, Foo foo) { + EntityTag tag = getCurrentTag(); + ResponseBuilder responseBuilder = request.evaluatePreconditions(tag); + if (responseBuilder != null) + return responseBuilder.build(); + else + return doUpdate(foo); +} +---- + +[source,java] +---- +@Inject +Request request; + +@PUT +public Response updateFoo(Foo foo) { EntityTag tag = getCurrentTag(); ResponseBuilder responseBuilder = request.evaluatePreconditions(tag); if (responseBuilder != null) @@ -118,23 +185,59 @@ The `SecurityContext` interface provides access to information about the security context of the current request. An instance of -`SecurityContext` can be injected into a class field or method parameter -using the `@Context` annotation. The methods of -`SecurityContext` provide access to the current user principal, +`SecurityContext` can be injected into a class field +using the `@Inject` annotation or as a resource method parameter. +The methods of `SecurityContext` provide access to the current user principal, information about roles assumed by the requester, whether the request arrived over a secure channel and the authentication scheme used. +[source,java] +---- +@Inject +SecurityContext securityContext; + +@GET +@Produces("text/plain") +public String getSecureData() { + if (securityContext.isUserInRole("admin")) { + return "Sensitive admin data"; + } + return "Public data"; +} +---- + [[providercontext]] ==== Providers The `Providers` interface allows for lookup of provider instances based on a set of search criteria. An instance of `Providers` can be injected -into a class field or method parameter using the `@Context` annotation. +into a class field using the `@Inject` annotation or as a resource method +parameter. This interface is expected to be primarily of interest to provider authors wishing to use other providers functionality. It is injectable in both client and server providers. +[source,java] +---- +@Provider +public class CustomMessageBodyWriter implements MessageBodyWriter<MyType> { + @Inject + Providers providers; + + @Override + public void writeTo(MyType t, Class<?> type, Type genericType, + Annotation[] annotations, MediaType mediaType, + MultivaluedMap<String, Object> httpHeaders, + OutputStream entityStream) throws IOException { + MessageBodyWriter<String> stringWriter = + providers.getMessageBodyWriter(String.class, String.class, + annotations, mediaType); + // Use the string writer to serialize MyType as a string + } +} +---- + [[resource_context]] ==== Resource Context @@ -151,7 +254,7 @@ ---- @Path("widgets") public class WidgetsResource { - @Context + @Inject private ResourceContext rc; @Path("{id}") @@ -161,7 +264,7 @@ } public class WidgetResource { - @Context + @Inject private HttpHeaders headers; public WidgetResource(String id) {...} @@ -180,7 +283,7 @@ ==== Configuration Both the client and the server runtime configurations are available for -injection via `@Context`. These configurations are available for +injection via `@Inject`. These configurations are available for injection in providers (client or server) and resource classes (server only). @@ -190,9 +293,10 @@ [source,java] ---- +@Provider public class LoggingFilter implements ClientRequestFilter { - @Context + @Inject private Configuration config; @Override
diff --git a/jaxrs-spec/src/main/asciidoc/chapters/environment/_javaee.adoc b/jaxrs-spec/src/main/asciidoc/chapters/environment/_javaee.adoc index cb76746..aa72655 100644 --- a/jaxrs-spec/src/main/asciidoc/chapters/environment/_javaee.adoc +++ b/jaxrs-spec/src/main/asciidoc/chapters/environment/_javaee.adoc
@@ -31,7 +31,7 @@ a Servlet container whose version is prior to 3. As explained in <<servlet_container>>, injection of -Servlet-defined types is possible using the `@Context` annotation. +Servlet-defined types is possible using the `@Inject` annotation. Additionally, web application’s `<context-param>` and servlet’s `<init-param>` can be used to define application properties passed to server-side features or injected into server-side JAX-RS components. See @@ -42,8 +42,14 @@ In a product that supports CDI, implementations MUST support the use of CDI-style Beans as root resource classes, providers and `Application` -subclasses. Providers and `Application` subclasses MUST be singletons or -use application scope. +subclasses. Providers and `Application` subclasses default to application +scope (see <<cdi-injection-model>>); it is RECOMMENDED that these classes +remain application-scoped, since they are typically stateless, but +applications MAY override the default with an explicit CDI scope. + +Implementations MUST support Jakarta CDI 5.0 or later. This version of CDI +is required for proper integration of Jakarta REST injection and CDI dependency +injection as described in <<cdi-injection-model>>. For example, assuming CDI is enabled via the inclusion of a `beans.xml` file, a CDI-style bean that can be defined as a JAX-RS resource as @@ -66,8 +72,372 @@ The example above takes advantage of the type-safe dependency injection provided in CDI by using another bean, of type `MyOtherCdiBean`, in -order to return a resource representation. See <<additional_reqs>> -for additional requirements on CDI-style Beans. +order to return a resource representation. See <<cdi-injection-model>> +for details on the CDI injection model. + +[[cdi-injection-model]] +===== Injection Model for CDI-Managed Resources + +When Jakarta REST resources and providers are managed as CDI beans, a hybrid +injection model applies that combines Jakarta REST parameter extraction with +CDI dependency injection. + +====== Bean Lifecycle + +CDI manages the bean lifecycle, including bean instantiation and destruction. +Jakarta REST defines the following CDI stereotype annotations that enable automatic +CDI discovery: + +* `@ApplicationPath` - annotated with `@ApplicationScoped`, applied to `Application` + subclasses to define the base URI for all resource URIs +* `@Path` - annotated with `@RequestScoped`, applied to resource classes to define + URI path templates +* `@Provider` - annotated with `@ApplicationScoped`, applied to provider classes + (message body readers/writers, exception mappers, filters, interceptors, etc.) + +The defined scopes ensure proper lifecycle management: `@ApplicationPath` and +`@Provider` annotated classes are application-scoped singletons, while `@Path` +annotated resource classes are request-scoped and created per-request by default. +Applications MAY override these default scopes by explicitly annotating classes +with different CDI scope annotations. + +====== Field Injection + +Fields in CDI-managed beans MUST use `@Inject` instead of the deprecated `@Context` +annotation. This applies to both Jakarta REST context types and Jakarta REST parameter +extraction: + +[source,java] +---- +@Path("/items") +public class ItemResource { + @Inject // Context type injection + UriInfo uriInfo; + + @Inject // CDI bean injection + ItemService service; + + @Inject + @QueryParam("filter") // Parameter extraction + String filter; + + @Inject + @PathParam("id") // Parameter extraction + String id; +} +---- + +All field injection is handled by CDI. Jakarta REST parameter annotations (`@QueryParam`, +`@PathParam`, `@HeaderParam`, `@MatrixParam`, `@CookieParam`, `@FormParam`, `@BeanParam`) +act as CDI qualifiers. Implementations MUST make these qualified injection points +resolvable through CDI, extracting the value from the current request context at +injection time, for any type a resource or provider declares—including +application-defined converter types and generic collections. Implementations MAY +satisfy this requirement using CDI producer methods, synthetic beans, or portable +extensions, as appropriate to the declared type. Where a producer method is used, it +MUST be `@Dependent` scoped and MAY use the CDI `InjectionPoint` API to determine the +parameter name from the qualifier annotation. + +====== Constructor Injection + +Constructor parameters in CDI-managed beans are injected using CDI. The constructor +MUST be annotated with `@Inject`. Jakarta REST-specific types (UriInfo, HttpHeaders, +etc.) and parameter annotations (`@QueryParam`, `@PathParam`, etc.) are made available +via CDI producers as described in <<cdi-producers>>. + +[source,java] +---- +@Path("/items") +public class ItemResource { + private final ItemService service; + private final UriInfo uriInfo; + private final String category; + + @Inject + public ItemResource(ItemService service, + UriInfo uriInfo, + @QueryParam("category") String category) { + this.service = service; + this.uriInfo = uriInfo; + this.category = category; + } +} +---- + +NOTE: Jakarta REST parameter annotations (`@QueryParam`, `@PathParam`, etc.) MUST +only be used on injection points of a bean whose scope guarantees a new bean +instance per Jakarta REST request (the default `@RequestScoped` scope for +`@Path`-annotated classes satisfies this). Applications that violate this +constraint have undefined results, including the possibility of a stale value +being retained and reused across unrelated requests. Implementations MAY detect +and reject known-unsafe usages at deployment time. + +====== Setter Method Injection + +CDI-managed beans MAY use setter methods annotated with `@Inject` to receive +Jakarta REST parameter values. The parameter annotation (`@PathParam`, `@QueryParam`, +etc.) may be placed on either the method or the method parameter: + +[source,java] +---- +@Path("/items/{id}") +public class ItemResource { + + private String id; + private String filter; + + // Annotation on parameter (recommended for CDI) + @Inject + public void setId(@PathParam("id") String id) { + this.id = id; + } + + // Annotation on method (legacy form) + @Inject + @QueryParam("filter") + public void setFilter(String filter) { + this.filter = filter; + } +} +---- + +When a parameter annotation is placed on the method rather than the parameter, +implementations MUST treat the annotation as if it were present on the method's +parameter for CDI qualifier resolution purposes. Only a single parameter is allowed +if annotations are placed on a method. Both forms are valid; the +parameter-level placement is the natural fit for CDI environments since CDI resolves +qualifiers from injection points (parameters), not from the enclosing method. + +====== Resource Method Parameter Injection + +Resource method parameters are resolved using a combination of Jakarta REST +parameter extraction and CDI producers. Implementations MAY use CDI to invoke +resource methods, but only the following parameter types are supported: + +Parameters are categorized as follows: + +* **Path, query, header, matrix, cookie, and form parameters**: Annotated with + `@PathParam`, `@QueryParam`, `@HeaderParam`, `@MatrixParam`, `@CookieParam`, + or `@FormParam`. These annotations are CDI qualifiers. Implementations MUST + provide CDI producers (typically `@Dependent` scoped) that use the `InjectionPoint` + API to extract the parameter name from the qualifier and retrieve the value from + the request context. + +* **Bean parameters**: Annotated with `@BeanParam` to inject a custom parameter + aggregator object. The `@BeanParam` annotation is a CDI qualifier. When running + with an active CDI container, the aggregator bean is created and injected by CDI + like any other CDI-managed type: `@Inject` fields are injected normally, and + fields annotated with parameter extraction annotations are resolved via the same + qualifier mechanism used for resource method parameters (see <<cdi-producers>>). + +* **Jakarta REST context types**: `Application`, `Configuration`, `HttpHeaders`, + `Providers`, `Request`, `ResourceContext`, `ResourceInfo`, `SecurityContext`, + `Sse`, and `UriInfo`. These types are identified by type alone. Implementations MUST + provide CDI producers as specified in <<cdi-producers>>. + +* **Entity parameter**: The request entity body, deserialized using a `MessageBodyReader`. + Identified as a parameter that is NOT annotated with any Jakarta REST parameter annotation, + is NOT a Jakarta REST context type (listed above), and is NOT `AsyncResponse` or `SseEventSink`. + Only one entity parameter is allowed per resource method. + +* **Jakarta REST-managed special parameters**: The following parameters are NOT + CDI beans and are handled directly by the Jakarta REST implementation: + ** **AsyncResponse**: Used for asynchronous processing. Identified by type alone + (no annotation required). Can only be injected as a resource method parameter. + ** **SseEventSink**: Used for server-sent events. Identified by type alone + (no annotation required). Can only be injected as a resource method parameter. + +NOTE: In previous versions, `AsyncResponse` required the `@Suspended` annotation. +This annotation is deprecated for removal in a future release. In CDI environments, +the type-alone approach (no annotation) is the recommended pattern. The `@Suspended` +annotation continues to work for backward compatibility. + +IMPORTANT: Application-provided CDI beans CANNOT be injected as resource method +parameters. To inject CDI beans into resources, use field injection with `@Inject` +or constructor injection as shown in <<cdi-injection-model>>. + +[source,java] +---- +@GET +@Path("{id}") +public Item get(@PathParam("id") String id, + @QueryParam("expand") String expand, + UriInfo uriInfo) { + return findItem(id, expand, uriInfo); +} + +@POST +@Consumes(MediaType.APPLICATION_JSON) +public Response create(Customer customer, // Jakarta REST deserializes from request body + UriInfo uriInfo) { + return Response.created(uriInfo.getAbsolutePath()).build(); +} + +@POST +@Path("async") +public void createAsync(Customer customer, + AsyncResponse asyncResponse) { // Type-checked, no annotation needed + asyncResponse.resume(Response.ok().build()); +} + +// Bean parameter example +public class SearchParams { + @Inject + @QueryParam("q") + String query; + + @Inject + @QueryParam("limit") + @DefaultValue("10") + int limit; + + @Inject + @HeaderParam("Accept-Language") + String language; +} + +@GET +@Path("search") +public List<Item> search(@BeanParam SearchParams params) { // CDI creates and injects params + return searchItems(params.query, params.limit, params.language); +} +---- + +NOTE: Jakarta CDI 5.0 provides method invokers (`jakarta.enterprise.invoke.Invoker`) +that enable frameworks to invoke methods with automatic CDI-based parameter injection. +Implementations MAY use this API to integrate Jakarta REST parameter conversion with +CDI injection. + +[[cdi-producers]] +====== Required CDI Producers + +Implementations MUST provide CDI producers for Jakarta REST context types and +parameter extraction to enable their injection into CDI-managed beans. + +**Context Type Producers** + +The following context types MUST be made available for CDI injection. The suggested +scope for each type is listed, though implementations MAY use different scopes if +appropriate: + +.Required CDI Producers for Jakarta REST Types +|=== +|Type |Suggested Scope |Description + +|`Application` +|`@ApplicationScoped` +|Application configuration and metadata + +|`Configuration` +|`@Dependent` +|Runtime configuration + +|`HttpHeaders` +|`@RequestScoped` +|Request HTTP headers + +|`Providers` +|`@ApplicationScoped` +|Provider instance lookup + +|`Request` +|`@RequestScoped` +|Request information for content negotiation + +|`ResourceContext` +|`@ApplicationScoped` +|Resource instance creation and initialization + +|`ResourceInfo` +|`@RequestScoped` +|Matched resource class and method information + +|`SecurityContext` +|`@RequestScoped` +|Security context of current request + +|`Sse` +|`@ApplicationScoped` +|Server-sent events support + +|`UriInfo` +|`@RequestScoped` +|URI and path information +|=== + +NOTE: The types `AsyncResponse` and `SseEventSink` are method-parameter-only types +and do NOT require CDI producers. These types are only available for injection as +resource method parameters and cannot be injected into fields or constructors. The +Jakarta REST implementation handles these types directly. + +**Parameter Extraction Producers** + +Implementations MUST provide CDI producers for Jakarta REST parameter annotations +that act as CDI qualifiers: + +* `@PathParam` - Extract path parameter values from URI path templates +* `@QueryParam` - Extract query parameter values from the request URI +* `@HeaderParam` - Extract HTTP header values +* `@MatrixParam` - Extract matrix parameter values from URI path segments +* `@CookieParam` - Extract cookie values +* `@FormParam` - Extract form parameter values from request entity +* `@BeanParam` - Create and populate a parameter aggregator bean + +These producers MUST be `@Dependent` scoped and could use the CDI `InjectionPoint` +API to: + +1. Inspect the qualifier annotation to determine the parameter name +2. Extract the value from the current request context +3. Convert the value to the target type using the same conversion rules as + specified in <<resource_field>> + +NOTE: Entity parameters do NOT require a CDI producer. They are handled directly +by the Jakarta REST implementation using `MessageBodyReader` instances to deserialize +the request body. + +NOTE: Parameter extraction producers are `@Dependent` scoped and extract values +from the current request context. CDI manages injection of these values into beans +according to CDI specification scope compatibility rules. Resource method parameters +are the recommended pattern as they are always evaluated during request processing, +regardless of bean scope. For advanced scenarios involving non-request-scoped beans, +consult the CDI specification regarding scope compatibility and the `Instance<T>` +pattern for deferred resolution. + +[[cdi-application-methods]] +===== CDI Bean Discovery and Application Methods + +In CDI-enabled environments, `@Path` and `@Provider` annotated classes are +CDI-managed beans, independent of what `Application.getClasses()` returns. +The `getClasses()` method controls which classes are used for Jakarta REST +request processing, not which classes are managed by CDI. Implementations MUST +obtain resource and provider instances from CDI for classes that are CDI beans. +For classes excluded from CDI bean management (e.g., via `@Vetoed`), +implementations MAY instantiate them directly. + +Instances from `Application.getSingletons()` are not CDI-managed. + +[[additional_reqs]] +==== Additional Requirements for Non-CDI Environments + +In environments that do not support CDI, the following additional requirements +apply when using Jakarta REST resource classes, providers or `Application` +subclasses: + +* For Jakarta REST resources and providers where the Jakarta REST implementation +participates in their creation and initialization, field and property +injection in these resources and providers MUST be performed prior to the +container invoking any `@PostConstruct` annotated method. For resources +and providers created by the application (e.g. instances returned via the +`Application.getSingletons()` method, or instances passed via +`Configurable.register`), this requirement does not apply. +* Support for constructor injection of Jakarta REST resources is OPTIONAL. +Portable applications MUST instead use fields or bean properties in +conjunction with a `@PostConstruct` annotated method. Implementations +SHOULD warn users about use of non-portable constructor injection. +* Implementations MUST NOT require use of `@Inject` or `@Resource` to +trigger injection of Jakarta REST annotated fields or properties. +Implementations MAY support such usage but SHOULD warn users about +non-portability. [[ejbs]] ==== Enterprise Java Beans (EJBs) @@ -115,9 +485,7 @@ with an application then exceptions thrown by an EJB resource class or provider method MUST be unwrapped and processed as described in <<method_exc>>. -See <<async_ejbs>> for more information on asynchronous EJB -methods and <<additional_reqs>> for additional requirements on -EJBs. +See <<async_ejbs>> for more information on asynchronous EJB methods. [[bv_support]] ==== Bean Validation @@ -163,24 +531,3 @@ `text/xml` and `application/xml` and media types of the form `application/*+xml`. -[[additional_reqs]] -==== Additional Requirements - -The following additional requirements apply when using CDI-style Beans or EJBs as resource classes, providers or `Application` -subclasses: - -* For JAX-RS resources and providers where the JAX-RS implementation -participates in their creation and initialization, field and property -injection in these resources and providers MUST be performed prior to the -container invoking any `@PostConstruct` annotated method. For resources -and providers created by the application (e.g. instances returned via the -`Application.getSingletons()` method, or instances passed via -`Configurable.register`), this requirement does not apply. -* Support for constructor injection of JAX-RS resources is OPTIONAL. -Portable applications MUST instead use fields or bean properties in -conjunction with a `@PostConstruct` annotated method. Implementations -SHOULD warn users about use of non-portable constructor injection. -* Implementations MUST NOT require use of `@Inject` or `@Resource` to -trigger injection of JAX-RS annotated fields or properties. -Implementations MAY support such usage but SHOULD warn users about -non-portability.
diff --git a/jaxrs-spec/src/main/asciidoc/chapters/environment/_servlet_container.adoc b/jaxrs-spec/src/main/asciidoc/chapters/environment/_servlet_container.adoc index e6a1914..cb74bae 100644 --- a/jaxrs-spec/src/main/asciidoc/chapters/environment/_servlet_container.adoc +++ b/jaxrs-spec/src/main/asciidoc/chapters/environment/_servlet_container.adoc
@@ -11,6 +11,22 @@ [[servlet_container]] === Servlet Container + +[NOTE] +==== +The use of `@Context` for injecting Servlet-defined types is deprecated. +In environments that support CDI and Jakarta Servlet, applications should use +CDI injection (`@Inject`) for Servlet-defined types as specified by the Jakarta +Servlet and Jakarta EE Platform specifications. Consult those specifications for +details on which Servlet types are available as CDI built-in beans. + +Implementations MUST NOT register a CDI bean for a Servlet-defined type if a +bean satisfying that type is already available (for example, one provided by +the Jakarta Servlet or Jakarta EE Platform CDI integration), to avoid ambiguous +dependency resolution. Where no such bean is available, implementations MAY +register their own CDI producer for these types as a fallback. +==== + The `@Context` annotation can be used to indicate a dependency on a Servlet-defined resource. A Servlet-based implementation MUST support injection of the following Servlet-defined types: `ServletConfig`,
diff --git a/jaxrs-spec/src/main/asciidoc/chapters/providers/_lifecycle_and_environment.adoc b/jaxrs-spec/src/main/asciidoc/chapters/providers/_lifecycle_and_environment.adoc index 122159c..7a1ec93 100644 --- a/jaxrs-spec/src/main/asciidoc/chapters/providers/_lifecycle_and_environment.adoc +++ b/jaxrs-spec/src/main/asciidoc/chapters/providers/_lifecycle_and_environment.adoc
@@ -63,16 +63,21 @@ parameter values. Note that a zero argument constructor is permissible under this rule. -A public constructor MAY include parameters annotated with -`@Context`—Chapter <<context>> defines the parameter types permitted for -this annotation. Since providers may be created outside the scope of a -particular request, only deployment-specific properties may be available -from injected interfaces at construction time; request-specific -properties are available when a provider method is called. If more than -one public constructor can be used then an implementation MUST use the -one with the most parameters. Choosing amongst constructors with the -same number of parameters is implementation specific, implementations -SHOULD generate a warning about such ambiguity. +In CDI environments, a constructor that declares parameters MUST be annotated +with `@Inject` and MAY include parameters for Jakarta REST context types and +parameter extraction as described in <<cdi-injection-model>>. A public +zero-argument constructor remains valid without `@Inject`, consistent with +normal CDI bean constructor rules. In non-CDI environments, a public constructor +MAY include parameters annotated with `@Context`—Chapter <<context>> defines the +parameter types permitted for this annotation. + +Since providers may be created outside the scope of a particular request, only +deployment-specific properties may be available from injected interfaces at +construction time; request-specific properties are available when a provider +method is called. If more than one public constructor can be used then an +implementation MUST use the one with the most parameters in non-CDI environments. +Choosing amongst constructors with the same number of parameters is +implementation specific, implementations SHOULD generate a warning about such ambiguity. [[provider_priorities]] ==== Priorities
diff --git a/jaxrs-spec/src/main/asciidoc/chapters/resources/_resource-classes.adoc b/jaxrs-spec/src/main/asciidoc/chapters/resources/_resource-classes.adoc index 27ac195..cd94f2a 100644 --- a/jaxrs-spec/src/main/asciidoc/chapters/resources/_resource-classes.adoc +++ b/jaxrs-spec/src/main/asciidoc/chapters/resources/_resource-classes.adoc
@@ -39,15 +39,26 @@ parameter values. Note that a zero argument constructor is permissible under this rule. -A public constructor MAY include parameters annotated with one of the -following: `@Context`, `@HeaderParam`, `@CookieParam`, `@MatrixParam`, -`@QueryParam` or `@PathParam`. However, depending on the resource class -lifecycle and concurrency, per-request information may not make sense in -a constructor. If more than one public constructor is suitable then an -implementation MUST use the one with the most parameters. Choosing -amongst suitable constructors with the same number of parameters is -implementation specific, implementations SHOULD generate a warning about -such ambiguity. +In CDI-enabled environments where the resource class is a CDI-managed bean, +the CDI container manages instantiation and constructor injection follows +CDI rules as described in <<cdi-injection-model>>. Constructor parameters +are injected by CDI, and Jakarta REST-specific types are made available +via CDI producers as specified in <<cdi-producers>>. + +In non-CDI environments, or for resources not managed by CDI, a public +constructor MAY include parameters annotated with one of the following: +`@HeaderParam`, `@CookieParam`, `@MatrixParam`, `@QueryParam` or `@PathParam`. +However, depending on the resource class lifecycle and concurrency, per-request +information may not make sense in a constructor. + +NOTE: The use of `@Context` in constructors is deprecated. Applications should +use CDI constructor injection in CDI-enabled environments, or use field/property +injection in non-CDI environments. + +In non-CDI environments if more than one public constructor is suitable then an +implementation MUST use the one with the most parameters. Choosing amongst suitable +constructors with the same number of parameters is implementation specific, +implementations SHOULD generate a warning about such ambiguity. Non-root resource classes are instantiated by an application and do not require the above-described public constructor.
diff --git a/jaxrs-spec/src/main/asciidoc/chapters/resources/_resource_field.adoc b/jaxrs-spec/src/main/asciidoc/chapters/resources/_resource_field.adoc index ab07dc3..01aeb15 100644 --- a/jaxrs-spec/src/main/asciidoc/chapters/resources/_resource_field.adoc +++ b/jaxrs-spec/src/main/asciidoc/chapters/resources/_resource_field.adoc
@@ -15,6 +15,10 @@ properties annotated with one the following annotations are set according to the semantics of the annotation: +NOTE: In CDI environments, field and bean property injection is handled by CDI +using the injection model described in <<cdi-injection-model>>. The parameter +extraction annotations listed below apply in both CDI and non-CDI environments. + `@MatrixParam`:: Extracts the value of a URI matrix parameter. `@QueryParam`:: @@ -25,25 +29,26 @@ Extracts the value of a cookie. `@HeaderParam`:: Extracts the value of a header. -`@Context`:: +`@Inject`:: Injects an instance of a supported resource, see chapters <<context>> - and <<environment>> for more details. + and <<environment>> for more details. In non-CDI environments, the + deprecated `@Context` annotation may be used instead; see + <<additional_reqs>> for additional requirements. Because injection occurs at object creation time, use of these -annotations (with the exception of `@Context`) on resource class fields -and bean properties is only supported for the default per-request -resource class lifecycle. An implementation SHOULD warn if resource -classes with other lifecycles use these annotations on resource class -fields or bean properties. +annotations on resource class fields and bean properties may depend on +resource class lifecycle and scope. See <<cdi-injection-model>> for +details on scope considerations in CDI environments. -A JAX-RS implementation is only required to set the annotated field and -bean property values of instances created by its runtime. Objects -returned by sub-resource locators (see <<sub_resources>>) are -expected to be initialized by their creator. +In non-CDI environments, a JAX-RS implementation is only required to +set the annotated field and bean property values of instances created +by its runtime. Objects returned by sub-resource locators (see <<sub_resources>>) +are expected to be initialized by their creator. In CDI environments, CDI manages +injection for all CDI beans including sub-resources. Valid parameter types for each of the above annotations are listed in -the corresponding Javadoc, however in general (excluding `@Context`) the -following types are supported: +the corresponding Javadoc, however in general the following types are +supported: 1. Types for which a `ParamConverter` is available via a registered `ParamConverterProvider`. See Javadoc for these classes for
diff --git a/jaxrs-spec/src/main/asciidoc/chapters/resources/_resource_method.adoc b/jaxrs-spec/src/main/asciidoc/chapters/resources/_resource_method.adoc index b8185c7..0d892f4 100644 --- a/jaxrs-spec/src/main/asciidoc/chapters/resources/_resource_method.adoc +++ b/jaxrs-spec/src/main/asciidoc/chapters/resources/_resource_method.adoc
@@ -53,12 +53,29 @@ [[entity_parameters]] ===== Entity Parameters -The value of a parameter not annotated with `@FormParam` or any of the -annotations listed in in <<resource_field>>, called the entity -parameter, is mapped from the request entity body. Conversion between an -entity body and a Java type is the responsibility of an entity provider, -see <<entity_providers>>. Resource methods MUST have at most one -entity parameter. +The entity parameter represents the request entity body and is mapped from the +request entity body using an entity provider. Conversion between an entity body +and a Java type is the responsibility of an entity provider, see +<<entity_providers>>. + +The entity parameter is identified as a parameter that is NOT annotated with `@FormParam` +or any of the annotations listed in <<resource_field>>, is NOT a Jakarta REST context +type (such as `UriInfo`, `HttpHeaders`, `Request`, etc.), and is NOT `AsyncResponse` +or `SseEventSink`. + +Resource methods MUST have at most one entity parameter. + +Example: + +[source,java] +---- +@POST +@Consumes(MediaType.APPLICATION_JSON) +public Response create(final Customer customer, final HttpHeaders headers) { + // customer is deserialized from request body + return Response.ok().build(); +} +---- [[resource_method_return]] ==== Return Type
diff --git a/jaxrs-spec/src/main/asciidoc/chapters/sse/_sse_broadcasting.adoc b/jaxrs-spec/src/main/asciidoc/chapters/sse/_sse_broadcasting.adoc index 9c43da1..0a0b0d7 100644 --- a/jaxrs-spec/src/main/asciidoc/chapters/sse/_sse_broadcasting.adoc +++ b/jaxrs-spec/src/main/asciidoc/chapters/sse/_sse_broadcasting.adoc
@@ -27,7 +27,7 @@ @Singleton public class SseResource { - @Context + @Inject private Sse sse; private volatile SseBroadcaster sseBroadcaster; @@ -40,7 +40,7 @@ @GET @Path("register") @Produces(MediaType.SERVER_SENT_EVENTS) - public void register(@Context SseEventSink eventSink) { + public void register(SseEventSink eventSink) { eventSink.send(sse.newEvent("welcome!")); sseBroadcaster.register(eventSink); }
diff --git a/jaxrs-spec/src/main/asciidoc/chapters/sse/_sse_server_api.adoc b/jaxrs-spec/src/main/asciidoc/chapters/sse/_sse_server_api.adoc index 341c951..f605a68 100644 --- a/jaxrs-spec/src/main/asciidoc/chapters/sse/_sse_server_api.adoc +++ b/jaxrs-spec/src/main/asciidoc/chapters/sse/_sse_server_api.adoc
@@ -24,8 +24,8 @@ @GET @Path("eventStream") @Produces(MediaType.SERVER_SENT_EVENTS) -public void eventStream(@Context SseEventSink eventSink, - @Context Sse sse) { +public void eventStream(SseEventSink eventSink, + Sse sse) { executor.execute(() -> { try (SseEventSink sink = eventSink) { eventSink.send(sse.newEvent("event1"));
diff --git a/jaxrs-spec/src/main/asciidoc/chapters/validation/_validation_and_error_reporting.adoc b/jaxrs-spec/src/main/asciidoc/chapters/validation/_validation_and_error_reporting.adoc index 9d30568..5ed1830 100644 --- a/jaxrs-spec/src/main/asciidoc/chapters/validation/_validation_and_error_reporting.adoc +++ b/jaxrs-spec/src/main/asciidoc/chapters/validation/_validation_and_error_reporting.adoc
@@ -13,7 +13,7 @@ Constraint annotations are allowed in the same locations as the following annotations: `@MatrixParam`, `@QueryParam`, `@PathParam`, -`@CookieParam`, `@HeaderParam` and `@Context`, _except_ in class +`@CookieParam`, `@HeaderParam` and `@Inject`, _except_ in class constructors and property setters. Specifically, they are allowed in resource method parameters, fields and property getters as well as resource classes, entity parameters and resource methods (return