Skip to content

Introduce CDI requirements for deprecated @Context injection #1340

Open
jamezp wants to merge 4 commits into
jakartaee:mainfrom
jamezp:cdi-updates
Open

Introduce CDI requirements for deprecated @Context injection #1340
jamezp wants to merge 4 commits into
jakartaee:mainfrom
jamezp:cdi-updates

Conversation

@jamezp

@jamezp jamezp commented Mar 30, 2026

Copy link
Copy Markdown
Member

This PR introduces the Jakarta Dependency and Context Injection requirements as a replacement for @Context injection. Note that most of this was taken from the original JakartaRest40.pdf. There are a few things I did differently however.

One is I changed the entity parameter annotation from @Entity to @EntityParam. One reason is there is already a jakarta.ws.rs.client.Entity type and that seemed confusing to me. The other is Jakarta Persistence already has a @Entity parameter. Using @EntityParam seemed the most natural with other parameter annotations. However, I'm open to suggestions like @MessageBody or anything else.

The second is I do think we should required the @Inject annotation on methods we want to use CDI injection on. The reason is implementations will need a way to know if we should be using CDI injection or the old way of parameter injection. For example consider a method like:

@GET
@Path("example")
public Response performGet(final MyCdiBean bean) {
    return Response.ok(bean.get()).build();
}

We have no way to know if MyCdiBean is an entity or it should be handled by the CDI container.

I'm opening this as a draft for now for further discussions. There are more tests that are needed for the @EntityParam and we may need to copy some other tests to use CDI instead of @Context injection. I didn't want to spend too much time on that until we agreed on the rest of the PR though.

This PR relates to:

We need to consider what needs to be done for #1214 and #1215 as well. I did not add any specification documentation about those as I wasn't sure where we wanted to go.

Note I added a OpenRewrite recipe here for adding the @EntityParam annotation. However, this might be the wrong place for this. I'd initially added it here to do some testing. It needs some updating though as I changed the requirements a bit. I've left it in the draft for now, but we can remove it before we merge.

@jamezp jamezp added this to the 5.0 milestone Mar 30, 2026
@FroMage

FroMage commented Mar 30, 2026

Copy link
Copy Markdown

I would like to suggest that the choice of calling this an entity in the first place was not necessarily helpful.

It was called an entity or message body in the first HTTP 1.1 RFC but a resource in REST and in the more recent HTTP RFC it is called a resource, a representation data or a payload or message payload or message body.

A lot of other frameworks, libraries or programming languages also call it a request body (as opposed to a response version).

I think we should consider a better name than entity for this annotation, and not only because it clashes with JPA's @Entity annotation.

Do we expect this annotation to be used to designate the response entity too?

@jamezp

jamezp commented Mar 30, 2026

Copy link
Copy Markdown
Member Author

I would like to suggest that the choice of calling this an entity in the first place was not necessarily helpful.

It was called an entity or message body in the first HTTP 1.1 RFC but a resource in REST and in the more recent HTTP RFC it is called a resource, a representation data or a payload or message payload or message body.

A lot of other frameworks, libraries or programming languages also call it a request body (as opposed to a response version).

Yeah, @RequestBody was another one I thought of. I only went with @EntityParam because it kind of "fit" with the other @*Param annotations. However, this is different and I honestly don't love the name. I just wanted to push something up to start the conversion so thank you :)

I think we should consider a better name than entity for this annotation, and not only because it clashes with JPA's @Entity annotation.

Do we expect this annotation to be used to designate the response entity too?

No, just on a request which is why @RequestyBody, @MessageBody, something like that makes more sense to me personally.

@FroMage

FroMage commented Mar 30, 2026

Copy link
Copy Markdown

I think, but this may be just me, I don't have data to back this up, but I think the entity term is confusing for new users. In a way that request body is not: I feel that most people understand what this is. I have some doubts about message body because I suspect fewer people associate HTTP with messages.

@FroMage

FroMage commented Mar 30, 2026

Copy link
Copy Markdown

But on the other hand, we already have Entity in several type names in the spec 😥

@jamezp

jamezp commented Mar 30, 2026

Copy link
Copy Markdown
Member Author

Agreed for sure. IMO @Entity so ambiguous and somewhat confusing. I think my personal preference would be @RequestBody because that is exactly what it is.

@mkarg

mkarg commented Mar 30, 2026

Copy link
Copy Markdown
Contributor

My personal preference would be @Entity because it is the word found in all the RFCs, so people dealing with specs will search for exactly that. It is not our job to criticize the IETF. It is our job to introduce CDI, solely.

@WhiteCat22

Copy link
Copy Markdown
Contributor

I am leaning towards @Entity, although I hate the potential collision with JPA.

My reasoning is that we already have jakarta.ws.rs.client.Entity in the Client and it might be confusing to users if the client and server don't match.

.post(Entity.entity(message, MediaType.TEXT_PLAIN));

...

public Response updateFoo(@Entity Foo foo) {
...
}

If we didn't already use Entity in the client I'd be more inclined towards @RequestBody with a "definition of terms" section in the REST spec to map @RequestBody to HTTP's Entity. However, since Entity is already well established in the REST spec I think we should continue to use it for consistency.

@jamezp

jamezp commented Mar 30, 2026

Copy link
Copy Markdown
Member Author

Another option is to simply not allow CDI for resource method parameters. Then we essentially have what we have now which is no annotation on the entity. The other types that require @Context can just use inference to be resolved. How the @*Param parameters are resolved becomes an implementation detail.

Comment thread jaxrs-spec/src/main/asciidoc/chapters/environment/_javaee.adoc Outdated
Comment thread jaxrs-spec/src/main/asciidoc/chapters/environment/_javaee.adoc Outdated
@FroMage

FroMage commented Mar 31, 2026

Copy link
Copy Markdown

My personal preference would be @Entity because it is the word found in all the RFCs, so people dealing with specs will search for exactly that. It is not our job to criticize the IETF. It is our job to introduce CDI, solely.

As I said in my comment, the latest RFC removed entity entirely, it's not called that anymore: https://datatracker.ietf.org/doc/html/rfc9110

For some reason, they did keep entity tag but that's probably an oversight.

I am not criticising IETF, I'm pointing out that nobody ever called these entities outside of Jakarta REST, and the latest RFC appears to agree with this observation.

@jamezp

jamezp commented Apr 1, 2026

Copy link
Copy Markdown
Member Author

It's seems like RFC9110 uses "content" so we could use @Content https://www.rfc-editor.org/rfc/rfc9110.html#name-content

HTTP messages often transfer a complete or partial representation as the message "content": a stream of octets sent after the header section, as delineated by the message framing.

If we really want to stick with something around entity I'd prefer @EntityParam to not be confused with or require a FQCN reference, the jakarta.ws.rs.client.Entity.

@FroMage

FroMage commented Apr 1, 2026

Copy link
Copy Markdown

It's seems like RFC9110 uses "content" so we could use @Content https://www.rfc-editor.org/rfc/rfc9110.html#name-content

Huh, I did not notice content when I listed all the other terms it uses. That one makes a lot of sense, given content types, content negociation…

Probably not as widespread as request body for a term, but definitely a lot more obvious to anyone than entity.

@mkarg

mkarg commented Apr 1, 2026

Copy link
Copy Markdown
Contributor

It's seems like RFC9110 uses "content" so we could use @Content https://www.rfc-editor.org/rfc/rfc9110.html#name-content

HTTP messages often transfer a complete or partial representation as the message "content": a stream of octets sent after the header section, as delineated by the message framing.

If we really want to stick with something around entity I'd prefer @EntityParam to not be confused with or require a FQCN reference, the jakarta.ws.rs.client.Entity.

@EntityParam seems to be straightforward, as it builds on the "Entity" word used in other parts of Jakarta REST, and extends the Param series of injection markers. +1 from me.

@mkarg

mkarg commented Apr 1, 2026

Copy link
Copy Markdown
Contributor

It's seems like RFC9110 uses "content" so we could use @Content https://www.rfc-editor.org/rfc/rfc9110.html#name-content

Huh, I did not notice content when I listed all the other terms it uses. That one makes a lot of sense, given content types, content negociation…

Probably not as widespread as request body for a term, but definitely a lot more obvious to anyone than entity.

IMHO @Content is far too easy to confuse with @Context.

@jamezp

jamezp commented Apr 30, 2026

Copy link
Copy Markdown
Member Author

I did a short talk about these changes today in this PR on the Jakarta EE Futures call. @jhanders34 had a, very good IMO, idea to not allow arbitrary CDI beans to be injected into resource methods which means we would not need the @EntityParam annotation for 5.0. Then in 6.0 when we remove @Context, we can add the @EntityParam annotation and then allow CDI bean injection into resource methods.

Without this approach we could break compatibility and require users to add @EntityParam to request body content parameters.

@mkarg

mkarg commented May 1, 2026

Copy link
Copy Markdown
Contributor

@jamezp I need to confess I somewhat got lost in the discussion. Could you please elaborate how that distinction in 5.0 and 6.0 changes anything? I am no CDI expect, so please bear with me. What problem arises from our current plan and why is that "very good IMO" idea the soltuion? 🤔

@jamezp

jamezp commented May 1, 2026

Copy link
Copy Markdown
Member Author

@mkarg That is a fair request and would help others too :) I'll work on something more detailed next week and work on updating this PR to reflect the plan.

REST 5.0

Add CDI full CDI support for resources, providers and applications for field injection and constructor injection. For resource methods, CDI will only replace the usage of @Context injection. Meaning you cannot inject an arbitrary CDI bean into a resource method.

Deprecate @Context, @Suspended annotations and the ContextResolver interface. We may want to deprecate the Providers.getContextResolver() too since we're deprecating the ContextResolver. However, maybe we don't need to deprecate the latter two. I'm open to either option.

Full backward compatibility, meaning @Context injection will still work as will the other API's. There is no need to add the @EntityParam annotation as the request body parameter will still be the "unknown" parameter.

REST 6.0

Remove the deprecated API's and add the @EntityParam (or whatever we decide to call it) and require it on the message body parameter. This will allow us to support full CDI injection for resource methods.

@mkarg

mkarg commented May 2, 2026

Copy link
Copy Markdown
Contributor

Thank you, James. As in the end the result will be the same (everbody needs to overhaul his existing applications and put @EntityParam on each single resource method), I do not see the actual benefit of this two-step way. Developers will get confused by a long and ongoing change path. Why not simply doing that cut in 5.0 directly?

*
* @author Marek Potociar
* @since 2.0
* @deprecated use Jakarta Context and Dependency injection

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should add since 5.0 to the JavaDocs also, so people have a better understanding which version supports what technology?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have the version in the @Deprecated annotation. We could add it here too I guess.

* 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 CDI prior to use.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As CDI is an abstract idea but not a concrete product, shouldn't it be "...by CDI prio..." (without "the")?

*
* @author Paul Sandoz
* @author Marc Hadley
* @see Context

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we need another cross reference mentioned, to make clear that these interfaces are injectable?

@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ApplicationScoped

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I wonder if providers can only be application scoped, or if it was valid to make them request scoped before?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why they couldn't be request scoped. I probably wouldn't suggest it, but I don't see why it would be an issue :)

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EntityParam {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

[[cdi-injection-model]]
===== Injection Model for CDI-Managed Resources

When Jakarta REST resources and providers are managed as CDI beans, a hybrid

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"When"? Isn't that mandatory now?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We haven't defined what needs to happen with SeBoostrap which is why I added this.


====== Resource Method Parameter Injection

Resource methods allow for parameter injection via CDI. The method MUST not be annotated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method MUST not be annotated with @Inject

Why should someone do that? Do we really have to explicitly say that?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The part of requiring @Inject for resource methods has been removed and we definitely shouldn't do that. My initial thought when I added it was that it would be easy for implementations to know if it was a CDI resource method or a legacy one.


* **Jakarta REST-managed special parameters**: The following parameters are NOT
CDI beans and are handled directly by the Jakarta REST implementation:
** **Entity parameter** (`@EntityParam`): The request entity body, deserialized using

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a technical reason why the entity should not be a CDI bean?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really see how it could be. You need the request to create the entity. If it was a CDI bean it would mean it could be injected into anything which doesn't have to be a Jakarta REST endpoint.

3. Convert the value to the target type using the same conversion rules as
specified in <<resource_field>>

NOTE: The `@EntityParam` annotation does NOT require a CDI producer. Entity parameters

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not understand this separation. Again, I am not a CDI expert, so bear with me. IMHO @EntityParam should be provided by a CDI producer. The runtime should be that CDI producer. To produce the instance, the runtime invokes MBRs. Wouldn't that be straightforward? 🤔

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about this more and I don't think it can be. We need the request to create the entity with a reader. CDI doesn't really need a request, at least not an HTTP one. We can't make it a CDI bean and assume it can just be injected let's say into a scheduled EJB.

[[contextprovider-migration]]
==== Migration to CDI Producers

Applications using `ContextResolver` should migrate to using CDI producers

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not see why we need to deprecate "ContextResolver". Couldn't we instead say that runtime MUST provide CDI producers for these classes, and MUST internally invoke the original context resolver in turn?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been wondering about this one as well. The ContextResolver likely doesn't need to be deprecated, so maybe we just don't deprecate which seems fine to me.

@jamezp

jamezp commented May 19, 2026

Copy link
Copy Markdown
Member Author

Thinking more about this, I'm not sure what advantage there is to allowing CDI injection into parameters. CDI beans can be injected at the instance level or in the constructor. I don't really see why we'd need them injected in resource methods.

If we don't allow CDI injection into resource methods, we can keep backwards compatibility much easier.

…otype annotations. Make the parameter annotations qualifiers. Added CDI as a required module.

Signed-off-by: James R. Perkins <jperkins@ibm.com>
@jamezp jamezp marked this pull request as ready for review June 16, 2026 19:46
@jamezp

jamezp commented Jun 16, 2026

Copy link
Copy Markdown
Member Author

What I've done is gone with the approach of removing the @EntityParam annotation. Arbitrary CDI are not allowed to be injected in resource methods. You can inject them via instance fields or constructor parameters though.

The same rules apply for determining the entity in a resource method. If the parameter is not annotated with @*Param, is not a known required context type, e.g. UriInfo, HttpHeaders, etc., or is of type AsyncResponse, then it is assumed to be the entity parameter.

I've removed the deprecation of the ContextResolver as a CDI producer is not really a direct replacement.

I also removed the OpenRewrite recipe and will publish it elsewhere.

jamezp added 3 commits June 16, 2026 13:56
Signed-off-by: James R. Perkins <jperkins@ibm.com>
instead of @context for resource injection.

Signed-off-by: James R. Perkins <jperkins@ibm.com>
Signed-off-by: James R. Perkins <jperkins@ibm.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants