CDI alignment: Servlet Spec beans Qualifier needed.
The Spec, Section 11, says:
A Servlet-based implementation MUST support injection of the following Servlet-defined types:
ServletConfig,ServletContext,HttpServletRequestandHttpServletResponse.
In the CDI environment, the implementation cannot provide the @Default CDI beans, the Servlet default beans can be provided by the Servlet Implementation, which leads to a CDI ambiguity. We can see that with Krazo (but any framework can start to provide the beans), which provides @Default HttpServletRequest and ServletContext CDI beans. If the implementation provides the @Default beans, we can see something like
WELD-001409: Ambiguous dependencies for type HttpServletRequest with qualifiers @Default at injection point [UnbackedAnnotatedField] @Inject private org.eclipse.krazo.core.Messages.request at org.eclipse.krazo.core.Messages.request(Messages.java:0) Possible dependencies:
- WELD%AbstractBuiltInBean%org.eclipse.krazo.cdi.KrazoCdiExtension%HttpServletRequest,
- org.glassfish.jersey.ext.cdi1x.internal.CdiComponentProvider$Hk2Bean@1c10d8ce
Hence, unless everyone starts to use @Inject @Any, the Jakarta REST should not provide the @Default beans, I believe. For Jakarta REST 4.0, it would be useful to provide a Qualifier that could be used in conjunction with @Inject instead of @Any to be sure to inject the correct instances.
Would any of @Rest, @RestInject, or maybe @Context be a good qualifier? Krazo is using @JaxRsContext for some beans (e.g. HttpServletResponse, UriInfo).
In the CDI environment, the implementation cannot provide the @Default CDI beans, the Servlet default beans can be provided by the Servlet Implementation, which leads to a CDI ambiguity. We can see that with Krazo (but any framework can start to provide the beans),
As was mentioned in the Jakarta EE platform call yesterday, really the only spec/api that should provide default beans (build-in beans) for these artefacts is the spec/api that owns them. Anything else should not do so.
Since HttpServletRequest comes from the Servlet spec, Servlet should provide the default beans.
Since HttpServletRequest comes from the Servlet spec, Servlet should provide the default beans.
Right. We have basically two options:
- Provide an independent qualifier to allow compatibility when migrating among implementations
- Let the implementation to choose their own qualifier
Well, we the third option:
- Drop the requirement and let the Servlet implementation provide the beans
There are some somewhat hacky ways you could achieve this in a CDI extension. However, I'd agree it seems best to drop the requirement. Jakarta REST should only be required to inject Jakarta REST types IMO.
Indeed, think of it the other way around; Servlet "suddenly" providing beans for injection of Jakarta REST and Jakarta Faces types. Would be rather weird.
And the fourth option:
- We do not want to be dependent on whether
Servletexposes the beans or not, so we provide a new object (ServletReferenceperhaps) that would have a reference to the servlet classes. Instead of allowing to inject directly the Servlet beans, we may have our own bean:
interface ServletReference {
ServletConfig getServletConfig();
ServletContext getServletContext();
HttpServletRequest getHttpServletRequest();
HttpServletResponse getHttpServletResponse();
}
I am a big fan of separating concerns. It is up to the Servlet API implementation to produce these beans. It is not the job of Jakarta REST anymore. The requirement should be dropped from section 11.
I also think it is not our responsibility to provide CDI injection for servlet classes. So I'm +1 for dropping the requirement as well.