JAX-RS and CDI in MicroProfile

330 views
Skip to first unread message

Laird Nelson

unread,
Nov 7, 2018, 2:19:31 PM11/7/18
to Eclipse MicroProfile
Hello; I'd like to open a discussion around the specification of the interaction of JAX-RS and CDI in MicroProfile.

TL;DR question:

How are these two independent specifications specified to interact in MicroProfile?

Or possibly equivalently:

Is the apparent lack of a MicroProfile specification or specification section governing the interaction of these two independent specifications deliberate?

The MicroProfile information that I could find on this subject reads as follows:

"CDI provides the base for a growing number of APIs included in MicroProfile 2.0."

"JAX-RS provides both standard client and server APIs for RESTful communication by MicroProfile 2.0 applications."


"Since the MicroProfile repo is an "umbrella" project, there will be no individual API or TCK generated for this component. Only this Specification will be generated and maintained to document the contents of each release."

Java EE 8, which also happens to include these specifications, has a lengthy section (EE.6.3 through EE.6.35) that discusses and specifies certain aspects of and imposes additional requirements on the interactions among its otherwise independent component specifications.  For example, there is a section that says:

"The [JAX-RS 2.1] specification defines a set of optional container-managed facilities and resources that are intended to be available in a Java EE container — all such features and resources must be made available."

It also has a lengthy section, EE.5.24, that covers how dependency injection is unified in Java EE.  (Regarding JAX-RS 2.1, it essentially says that CDI needs to be "in charge" of @Inject-annotated injection points (this should surprise no one, but it is specified, not left up to implementations).)

My point is: the interaction specification between the otherwise entirely independent CDI and JAX-RS specifications in the Java EE platform is spelled out in the Java EE platform specification.

Since:
  • a MicroProfile implementation is not required to support the Servlet specification, and
  • …the JAX-RS specification defines publishing of an application only in terms of servlets (section 2.3.1 of the JAX-RS specification basically says, hey, you can publish a non-servlet application almost any way you like), and 
  • …CDI doesn't make mention of JAX-RS, and
  • …JAX-RS doesn't make mention of CDI but
  • …MicroProfile conceptually bundles CDI and JAX-RS but
  • …doesn't say anything about their interaction
…I therefore wonder: what does a JAX-RS application with CDI in the picture look like in the MicroProfile world?

Sketchy edge cases ranging from the silly to the real that immediately come to mind in no particular order (assume for the thought experiment a MicroProfile implementation without Servlet and with CDI 2.0 at its core (i.e. not an application server like Glassfish)):
  • I have a portable extension on the classpath and set up properly in META-INF/services.  It creates an Application instance (which either does or does not return something from its getClasses() and/or getSingletons() methods) and adds it to the CDI container.  Otherwise I don't really do anything.  I start the MicroProfile implementation.  What should happen?  Anything?  Should this remain undefined?
  • I have an Application class simply on the classpath and some resource classes that it mentions in its getClasses() return value.  I don't do anything else, i.e. I don't register the Application in any way programmatically.  I start the MicroProfile implementation in some way.  The Application and resource classes are not annotated with any bean-defining annotations or scopes, so assuming they are processed in some way I am expecting them to have their JAX-RS-mandated default singleton and per-request lifecycles, respectively.  What happens?  Are they processed?  Should they not be?  Should this remain undefined?
  • I have no Application class at all.  I have some resource classes lying around on the classpath with @Path on them.  The JAX-RS specification indicates that scanning should happen in the case of a .war file, but this isn't a .war file.  What should happen?  Is this legal?  What path will everything be rooted at, if anything happens at all?  Should this remain undefined?
  • I have a resource class on the classpath with a bean-defining annotation on it.  The same resource class shows up in my Application's getClasses().  What should happen?
…and so on.

Looking forward to any and all discussion on all this.

Best,
Laird

Emily Jiang

unread,
Nov 7, 2018, 4:32:15 PM11/7/18
to Eclipse MicroProfile
Hi Laird,

MicroProfile does not specify any extra behaviour difference over and above what Java EE7/8 defined for JAX-RS and CDI. In MicroProfile 2.0, JAX-RS 2.1 and CDI 2.0 are certified against Java EE8 corresponding TCKs. The interaction between JAX-RS and CDI are defined in EE7/8 spec under the table EE 6-3.

JAX-RS resources are not CDI beans and they support injection and interceptor. A microservice with beans.xml file or beans.xml with bean-discovery-mode=annotated will be scanned for bean-defining annotations. If there are bean-defining annotations, CDI is enabled. JAX-RS resources within it will be able to use @Inject to inject any beans.

The Application class in JAX-RS should not contribute towards CDI at all. The way to make your microservice to be CDI enabled is to have a beans.xml (empty or bean-discovery-mode=all) or containing bean defining annotations.

HTH
Thanks
Emily

Laird Nelson

unread,
Nov 7, 2018, 4:40:39 PM11/7/18
to Eclipse MicroProfile
On Wednesday, November 7, 2018 at 1:32:15 PM UTC-8, Emily Jiang wrote:
MicroProfile does not specify any extra behaviour difference over and above what Java EE7/8 defined for JAX-RS and CDI.

Does it actually specify that behavior?  Where is it written that MicroProfile implementations must behave like Java EE 7 in this regard?  I probably missed something.
 
In MicroProfile 2.0, JAX-RS 2.1 and CDI 2.0 are certified against Java EE8 corresponding TCKs. The interaction between JAX-RS and CDI are defined in EE7/8 spec under the table EE 6-3. 

Is the EE platform specification part of MicroProfile in some way?

Best,
Laird

Ken Finnigan

unread,
Nov 7, 2018, 4:45:44 PM11/7/18
to Eclipse MicroProfile
Eclipse MicroProfile does not include any Java EE umbrella spec, so the integration of how CDI and JAX-RS works in Java EE does not apply.

At a previous Architecture meeting we discussed this: https://github.com/eclipse/microprofile/issues/49

The agreement was that it made sense for MicroProfile to define the integration and require JAX-RS Resources to be @RequestScoped, in the absence of any other scope.

However, currently MicroProfile does not have any type of umbrella specification. It's something that's needed so that we can define these types of integrations and in addition a TCK to test for it as well. It's on the list, but we haven't done it yet. My hope is we can have something for MP 2.2 in February.

Ken

Laird Nelson

unread,
Nov 7, 2018, 5:54:03 PM11/7/18
to Eclipse MicroProfile
On Wednesday, November 7, 2018 at 1:45:44 PM UTC-8, Ken Finnigan wrote:
Eclipse MicroProfile does not include any Java EE umbrella spec, so the integration of how CDI and JAX-RS works in Java EE does not apply.

That's what I thought.
 
At a previous Architecture meeting we discussed this: https://github.com/eclipse/microprofile/issues/49

Ah; thanks for the issue reference.
 
The agreement was that it made sense for MicroProfile to define the integration and require JAX-RS Resources to be @RequestScoped, in the absence of any other scope.

Yes.
 
However, currently MicroProfile does not have any type of umbrella specification. It's something that's needed so that we can define these types of integrations and in addition a TCK to test for it as well. It's on the list, but we haven't done it yet.

1000% agreed.  Many things open up and/or get complicated as you know when CDI is the nucleus, since it defines its own component model, and since JAX-RS applications that are not Servlet applications are, by spec, wide open.
 
My hope is we can have something for MP 2.2 in February.

I'm very interested in this; thanks.

Best,
Laird

Antoine Sabot-Durand

unread,
Nov 8, 2018, 5:14:11 AM11/8/18
to microp...@googlegroups.com
JAX-RS does mention CDI on section 10.2.3 for JAX-RS 2.0 and 11.2.3
for JAX-RS 2.1

"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."

IMO, problem is more on the CDI side and bean discovery mode. Without
umbrella spec, some impl assume "all" as bean discovery and others
"annotated".

Antoine
> --
> You received this message because you are subscribed to the Google Groups "Eclipse MicroProfile" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to microprofile...@googlegroups.com.
> To post to this group, send email to microp...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/microprofile/afad2b5e-fb49-4b15-95b2-f478da3a558c%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Santiago Pericas-Geertsen

unread,
Nov 8, 2018, 10:36:29 AM11/8/18
to microp...@googlegroups.com
All,

Some premises to help with the discussion:

* From a JAX-RS perspective, subclassing Application is the only way to guarantee portability

* As Laird indicated, the JAX-RS spec recommends class scanning in Servlet environments. For that purpose, it uses annotations such as @Path (resources) and @Provider (providers). Class scanning is (loosely) enabled by not providing an Application subclass or by providing one that returns nothing.

* By default JAX-RS resource classes are per-request and all providers are singletons

I don’t believe MP says anything about Application subclasses being optional (does it?), so let’s assume that they are not as in vanilla JAX-RS. Then,

(1) When an Application subclass is (somehow) discovered, should it be automatically be annotated with @ApplicationScoped if not already? What if it has a different scope?

(2) Application.getClasses() can return resources and providers. In the absence of scope annotations, resources should be @RequestScoped (as proposed elsewhere) and providers should be @ApplicationScoped.

(3) Application.getSingletons() may return instances that are not CDI beans. In MP environments, the use of this method should be (highly) discouraged in favor of @ApplicationScoped classes in (2).

So how can (2) be implemented? If in a CDI extension (discovery mode all?), it will need to annotate all resources and providers as it doesn’t know which ones will be returned by Application.getClasses(). Unless the @Provider annotation is mandated (see Servlet discussion above), detecting providers will require inspection of base types.

In any case, an Application subclass should be the source of truth regardless of what CDI happens to discover during its scanning phase.

If MP wants to support JAX-RS applications relying exclusively on scanning, without an Application subclass, then that would imply no filtering, everything that CDI discovers would be made part of the application —with similar default scopes as mentioned above.

— Santiago
> To view this discussion on the web visit https://groups.google.com/d/msgid/microprofile/CABu-YBSmK25j7XHpB%3DCOM--3We6mvbPk5W6Xq9fvFi00JDn31A%40mail.gmail.com.

Laird Nelson

unread,
Nov 8, 2018, 12:29:57 PM11/8/18
to Eclipse MicroProfile
On Thursday, November 8, 2018 at 2:14:11 AM UTC-8, Antoine Sabot-Durand wrote:
JAX-RS does mention CDI on section 10.2.3 for JAX-RS 2.0 and 11.2.3
for JAX-RS 2.1

"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."

Thanks; not sure how I missed that!

IMO, problem is more on the CDI side and bean discovery mode. Without
umbrella spec, some impl assume "all" as bean discovery and others
"annotated".

Right.

I'm also interested in cases where, say, we are in annotated bean discovery mode, an Application returns A.class from its getClasses() method, but A.class is not a CDI bean (it doesn't have a bean defining annotation on it).  Clearly in this case A.class will be a resource class, and the lifecycle of its instances will be managed by JAX-RS (per-request).  Now suppose a portable extension independently adds A.class as an annotated type, thus making A.class a CDI bean as well.  Is this permitted?  Defined?  Legal?  I suppose this particular edge case is more of a JAX-RS question than a MicroProfile question, but it is germane to the overall effort.

Best,
Laird

Laird Nelson

unread,
Nov 8, 2018, 2:30:46 PM11/8/18
to Eclipse MicroProfile
On Thursday, November 8, 2018 at 7:36:29 AM UTC-8, Santiago Pericas-Geertsen wrote:
 * From a JAX-RS perspective, subclassing Application is the only way to guarantee portability

Yes, but as Antoine pointed out section 11.2.3 in JAX-RS 2.1 expands (and/or confuses!) these portability rules for all MicroProfile implementations (a MicroProfile implementation is by definition a "product that supports CDI").
 
 * As Laird indicated, the JAX-RS spec recommends class scanning in Servlet environments. For that purpose, it uses annotations such as @Path (resources) and @Provider (providers). Class scanning is (loosely) enabled by not providing an Application subclass or by providing one that returns nothing.

Not just Servlet.  Because MicroProfile implementations fall under the category of "a product that supports CDI", it means that regardless of whether I have an Application subclass or not, CDI bean discovery must be in play, according to section 11.2.3 of the JAX-RS specification.  (The JAX-RS specification itself in isolation has many issues here IMHO: should an instance returned by Application#getSingletons() trump a discovered bean of the same class?  But normally Application#getClasses() trumps Application#getSingletons()….)

(Playing devil's advocate, there might be some quibbling over the mysterious and ill-defined "CDI-style Beans" moniker.  Does this mean an honest-to-goodness CDI bean (a source of contextual instances) (at the time the specification was written CDI was new so maybe the terminology was a little off here), or an unmanaged instance that supports injection?)

 I don’t believe MP says anything about Application subclasses being optional (does it?), so let’s assume that they are not as in vanilla JAX-RS. Then,

For the sake of discussion, sure, but bear in mind that if in a "product that supports CDI" such as a MicroProfile implementation JAX-RS "implementations MUST support the use of CDI-style Beans as root resource classes", then an Application subclass would be optional, assuming "CDI-style Beans" means "CDI beans".
 
 (1) When an Application subclass is (somehow) discovered, should it be automatically be annotated with @ApplicationScoped if not already? What if it has a different scope?

The only muddy area here is, IMHO, the meaning of the word "singletons" in section 11.2.3 of JAX-RS specification where it says "Providers and Application subclasses MUST be singletons or use application scope."

If we replace "singletons" with "CDI unmanaged instances that are instantiated only once but that also support injection of dependencies", that suggests one thing, and if we replace "singletons" with "classes annotated with javax.inject.Singleton" that suggests another.  From the fact that "application scope" is used at the end of this sentence, which is a well-defined CDI term, I'm assuming that "singleton" is actually shorthand for, effectively, "classes annotated with javax.inject.Singleton" and the behavior that JSR-330 and CDI require of such classes.

This matters when considering your (3) below.
 
(2) Application.getClasses() can return resources and providers. In the absence of scope annotations, resources should be @RequestScoped (as proposed elsewhere) and providers should be @ApplicationScoped.

Right; the second clause should read: "and provider classes present in the return value of Application#getClasses() should be treated as if they were annotated with either javax.inject.Singleton or javax.enterprise.context.ApplicationScoped".  The "either" part here means the umbrella specification should clarify this.
 
 (3) Application.getSingletons() may return instances that are not CDI beans.

Yes!  And furthermore it seems to be the intent of the JAX-RS specification that such objects should be injected by CDI when CDI is in the picture.  I'm not sure this part is explicitly spelled out in JAX-RS though.
 
In MP environments, the use of this method should be (highly) discouraged in favor of @ApplicationScoped classes in (2).

Yes but!  It's still possible.
 
So how can (2) be implemented?

Brainstorming, but (flailing wildly with flaws I'm sure) hopefully you get the general idea:
  • A portable extension uses CDI's Unmanaged facilities to instantiate and perform dependency injection on the Application subclass so 11.2.3 is honored
  • The portable extension creates a Bean whose creation method returns the unmanaged instance, perhaps with injection points removed (since injection was already performed) or other shenanigans to ensure DI doesn't happen twice (this permits Application to be injected into other CDI beans, which is required by 11.2.3)
  • The portable extension calls getClasses() and getSingletons() on the resulting instance.  For classes discovered this way, they are added as annotated types.  For singletons discovered this way, custom beans are added representing them. 
Or, maybe? assuming your JAX-RS implementation does things properly and has a properly implemented CDI integration library (see Jersey, maybe), you might get really lucky and be able to simply do something like the following when the @Initialized(ApplicationScoped.class) Object event is fired:

RuntimeDelegate.createEndpoint(new Unmanaged<Application>().newInstance().produce().inject().postConstruct().get(), someEndpointClass);

I don't know offhand, for example, whether Jersey-plus-its-CDI-integration-library properly implements all of the stuff we just discussed around section 11.2.3.  I'm guessing it misses a few edge cases but maybe you know differently.

If in a CDI extension (discovery mode all?), it will need to annotate all resources and providers as it doesn’t know which ones will be returned by Application.getClasses(). Unless the @Provider annotation is mandated (see Servlet discussion above), detecting providers will require inspection of base types.

Well, or a portable extension that looks them up from META-INF/services or whatnot and adds them programmatically, or other programmatic approaches.
 
 In any case, an Application subclass should be the source of truth regardless of what CDI happens to discover during its scanning phase.

This is where things get very murky.  I do agree with your interpretation, but perhaps "support the use of CDI-style Beans as root resource classes, providers and Application subclasses" means something above and beyond this?  It's not clear to me whether the scanning that "support" implies is to be merged into the results of Application#getClasses() and Application#getSingletons() or superseded by them.
 
 If MP wants to support JAX-RS applications relying exclusively on scanning, without an Application subclass,

My personal read is that according to section 11.2.3 it must.

Interestingly, all of these questions seem to be about the JAX-RS specification in isolation!

Best,
Laird

Raymond Auge

unread,
Nov 15, 2018, 10:02:04 AM11/15/18
to Eclipse MicroProfile


On Thu, Nov 8, 2018, 20:30 Laird Nelson <ljne...@gmail.com wrote:
On Thursday, November 8, 2018 at 7:36:29 AM UTC-8, Santiago Pericas-Geertsen wrote:
 * From a JAX-RS perspective, subclassing Application is the only way to guarantee portability

Yes, but as Antoine pointed out section 11.2.3 in JAX-RS 2.1 expands (and/or confuses!) these portability rules for all MicroProfile implementations (a MicroProfile implementation is by definition a "product that supports CDI").

I'm of the opinion that MicroProfile, by definition, has already taken the position that, where there is doubt, everything that can should be defined in terms of CDI. (That was a mouthful). I believe this will help stabilize debatable mechanics such as those found in the JAX-RS spec (through no fault of their own, just that at the time there was a less structured environment to work with, which is not the case with MP).

I sincerely think that care should be taken to clarify the behaviours so there are no doubts even if it means accepting a specific interpretation and making it the rule.

 
 * As Laird indicated, the JAX-RS spec recommends class scanning in Servlet environments. For that purpose, it uses annotations such as @Path (resources) and @Provider (providers). Class scanning is (loosely) enabled by not providing an Application subclass or by providing one that returns nothing.

Not just Servlet.  Because MicroProfile implementations fall under the category of "a product that supports CDI", it means that regardless of whether I have an Application subclass or not, CDI bean discovery must be in play, according to section 11.2.3 of the JAX-RS specification.  (The JAX-RS specification itself in isolation has many issues here IMHO: should an instance returned by Application#getSingletons() trump a discovered bean of the same class?  But normally Application#getClasses() trumps Application#getSingletons()….)

(Playing devil's advocate, there might be some quibbling over the mysterious and ill-defined "CDI-style Beans" moniker.  Does this mean an honest-to-goodness CDI bean (a source of contextual instances) (at the time the specification was written CDI was new so maybe the terminology was a little off here), or an unmanaged instance that supports injection?)

 I don’t believe MP says anything about Application subclasses being optional (does it?), so let’s assume that they are not as in vanilla JAX-RS. Then,

For the sake of discussion, sure, but bear in mind that if in a "product that supports CDI" such as a MicroProfile implementation JAX-RS "implementations MUST support the use of CDI-style Beans as root resource classes", then an Application subclass would be optional, assuming "CDI-style Beans" means "CDI beans".

I fully agree. Application is implied optional in those terms.

One doubt is; what would it mean to then have both root level resources AND an application.. or more than one application?

- 0 application + n resources implies a "default" application?
- 1 application overrides/replaces the "default" application
- n applications is an error?

 
 (1) When an Application subclass is (somehow) discovered, should it be automatically be annotated with @ApplicationScoped if not already? What if it has a different scope?

I do not agree that any magical extra work should be done here. I think that because we have the environment already defined as CDI, applications require a scope and the scope should be @ApplicationScoped. This is clear, precise, leaves no room for interpretation. If an implementation of microprofile wanted to do something such as warn about an unannotated Application class, then by all means. If the implementation just wants to load it, fine, but that should be non-portable (or if you wish, "value added").


The only muddy area here is, IMHO, the meaning of the word "singletons" in section 11.2.3 of JAX-RS specification where it says "Providers and Application subclasses MUST be singletons or use application scope."

If we replace "singletons" with "CDI unmanaged instances that are instantiated only once but that also support injection of dependencies", that suggests one thing,
and if we replace "singletons" with "classes annotated with javax.inject.Singleton" that suggests another.  From the fact that "application scope" is used at the end of this sentence, which is a well-defined CDI term, I'm assuming that "singleton" is actually shorthand for, effectively, "classes annotated with javax.inject.Singleton" and the behavior that JSR-330 and CDI require of such classes.

Since CDI (at least 2.0) has _relatively_ strong wording against the use of Singleton, I would use the interpretation "CDI unmanaged instances that are instantiated only once but that also support injection of dependencies".


This matters when considering your (3) below.
 
(2) Application.getClasses() can return resources and providers. In the absence of scope annotations, resources should be @RequestScoped (as proposed elsewhere) and providers should be @ApplicationScoped.

Right; the second clause should read: "and provider classes present in the return value of Application#getClasses() should be treated as if they were annotated with either javax.inject.Singleton or javax.enterprise.context.ApplicationScoped".  The "either" part here means the umbrella specification should clarify this.

Completely agree this need to be clarified.

 
 (3) Application.getSingletons() may return instances that are not CDI beans.

Yes!  And furthermore it seems to be the intent of the JAX-RS specification that such objects should be injected by CDI when CDI is in the picture.  I'm not sure this part is explicitly spelled out in JAX-RS though.

Also agreed.

 
In MP environments, the use of this method should be (highly) discouraged in favor of @ApplicationScoped classes in (2).

Yes but!  It's still possible.

One possibility is to raise this as a cdi definition error.

 
So how can (2) be implemented?

Brainstorming, but (flailing wildly with flaws I'm sure) hopefully you get the general idea:
  • A portable extension uses CDI's Unmanaged facilities to instantiate and perform dependency injection on the Application subclass so 11.2.3 is honored
  • portable extension creates a Bean whose creation method returns the unmanaged instance, perhaps with injection points removed (since injection was already performed) or other shenanigans to ensure DI doesn't happen twice (this permits Application to be injected into other CDI beans, which is required by 11.2.3)
  • The portable extension calls getClasses() and getSingletons() on the resulting instance.  For classes discovered this way, they are added as annotated types.  For singletons discovered this way, custom beans are added representing them. 
Or, maybe? assuming your JAX-RS implementation does things properly and has a properly implemented CDI integration library (see Jersey, maybe), you might get really lucky and be able to simply do something like the following when the @Initialized(ApplicationScoped.class) Object event is fired:

RuntimeDelegate.createEndpoint(new Unmanaged<Application>().newInstance().produce().inject().postConstruct().get(), someEndpointClass);

I don't know offhand, for example, whether Jersey-plus-its-CDI-integration-library properly implements all of the stuff we just discussed around section 11.2.3.  I'm guessing it misses a few edge cases but maybe you know differently.

If in a CDI extension (discovery mode all?), it will need to annotate all resources and providers as it doesn’t know which ones will be returned by Application.getClasses(). Unless the @Provider annotation is mandated (see Servlet discussion above), detecting providers will require inspection of base types.

Well, or a portable extension that looks them up from META-INF/services or whatnot and adds them programmatically, or other programmatic approaches.
 
 In any case, an Application subclass should be the source of truth regardless of what CDI happens to discover during its scanning phase.

This is where things get very murky.  I do agree with your interpretation, but perhaps "support the use of CDI-style Beans as root resource classes, providers and Application subclasses" means something above and beyond this?  It's not clear to me whether the scanning that "support" implies is to be merged into the results of Application#getClasses() and Application#getSingletons() or superseded by them.
 
 If MP wants to support JAX-RS applications relying exclusively on scanning, without an Application subclass,

My personal read is that according to section 11.2.3 it must.

Interestingly, all of these questions seem to be about the JAX-RS specification in isolation!

I do agree, the JAX-RS spec left much to interpretation. MP has the opportunity to make this a much better experience for both developers and implementors.

To sum up a recommendation I feel would do that:

- applications require @ApplicationScoped
- root level resources and providers require a scope; resources=@RequestScoped, providers=@ApplicationScoped
- 0 applications + n resources is interpreted as "default"; new Application() {}
- 1 application overrides "default"
- n applications raises CDI definition error??
- getClasses()
-- a class found to be existing annotated type (already discovered by CDI) must raise a definition error, otherwise it is added as an annotated type
-- resources=@RequestScoped
-- providers=@ApplicationScoped
- getSingletons()
-- are "CDI unmanaged instances that are instantiated only once but that also support injection of dependencies"
-- I don't see why these should be added as beans because they may have been injected from beans...

This leans toward favouring beans over getClasses/getSingletons model though it allows them to still work for legacy. However it limits the mixing and matching of the modes such that it's not so difficult to implement due to well defined rules.

Sincerely,
- Ray


Best,
Laird

--
You received this message because you are subscribed to the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this group and stop receiving emails from it, send an email to microprofile...@googlegroups.com.
To post to this group, send email to microp...@googlegroups.com.

Santiago Pericas-Geertsen

unread,
Nov 15, 2018, 11:37:37 AM11/15/18
to microp...@googlegroups.com

 See inline …


On Nov 15, 2018, at 10:01 AM, Raymond Auge <raymon...@liferay.com> wrote:

I sincerely think that care should be taken to clarify the behaviours so there are no doubts even if it means accepting a specific interpretation and making it the rule.

 +1


 
 * As Laird indicated, the JAX-RS spec recommends class scanning in Servlet environments. For that purpose, it uses annotations such as @Path (resources) and @Provider (providers). Class scanning is (loosely) enabled by not providing an Application subclass or by providing one that returns nothing. 

Not just Servlet.  Because MicroProfile implementations fall under the category of "a product that supports CDI", it means that regardless of whether I have an Application subclass or not, CDI bean discovery must be in play, according to section 11.2.3 of the JAX-RS specification.  (The JAX-RS specification itself in isolation has many issues here IMHO: should an instance returned by Application#getSingletons() trump a discovered bean of the same class?  But normally Application#getClasses() trumps Application#getSingletons()….)

(Playing devil's advocate, there might be some quibbling over the mysterious and ill-defined "CDI-style Beans" moniker.  Does this mean an honest-to-goodness CDI bean (a source of contextual instances) (at the time the specification was written CDI was new so maybe the terminology was a little off here), or an unmanaged instance that supports injection?)

 I don’t believe MP says anything about Application subclasses being optional (does it?), so let’s assume that they are not as in vanilla JAX-RS. Then, 

For the sake of discussion, sure, but bear in mind that if in a "product that supports CDI" such as a MicroProfile implementation JAX-RS "implementations MUST support the use of CDI-style Beans as root resource classes", then an Application subclass would be optional, assuming "CDI-style Beans" means "CDI beans".

I fully agree. Application is implied optional in those terms.

 If Application subclasses are optional, how are JAX-RS providers such as filters, interceptors, context providers, etc. discovered? Those are also part of a JAX-RS application. In a Servlet environment, they are required to be annotated by @Provider for discovery purposes. Alternatively, super-types can be inspected.

 This requires some clarifications.


One doubt is; what would it mean to then have both root level resources AND an application.. or more than one application?

- 0 application + n resources implies a "default" application?

 Seems reasonable module the issue with providers (see above).

- 1 application overrides/replaces the "default” application

 Yes, see remarks below.

- n applications is an error?

 It should be.


 
 (1) When an Application subclass is (somehow) discovered, should it be automatically be annotated with @ApplicationScoped if not already? What if it has a different scope? 

I do not agree that any magical extra work should be done here. I think that because we have the environment already defined as CDI, applications require a scope and the scope should be @ApplicationScoped. This is clear, precise, leaves no room for interpretation. If an implementation of microprofile wanted to do something such as warn about an unannotated Application class, then by all means. If the implementation just wants to load it, fine, but that should be non-portable (or if you wish, "value added”).

 Yes, force the use of scope CDI annotations.




This matters when considering your (3) below.
 
(2) Application.getClasses() can return resources and providers. In the absence of scope annotations, resources should be @RequestScoped (as proposed elsewhere) and providers should be @ApplicationScoped.

Right; the second clause should read: "and provider classes present in the return value of Application#getClasses() should be treated as if they were annotated with either javax.inject.Singleton or javax.enterprise.context.ApplicationScoped".  The "either" part here means the umbrella specification should clarify this.

Completely agree this need to be clarified.

 
 (3) Application.getSingletons() may return instances that are not CDI beans.

Yes!  And furthermore it seems to be the intent of the JAX-RS specification that such objects should be injected by CDI when CDI is in the picture.  I'm not sure this part is explicitly spelled out in JAX-RS though.

Also agreed.

 
In MP environments, the use of this method should be (highly) discouraged in favor of @ApplicationScoped classes in (2). 

Yes but!  It's still possible.

One possibility is to raise this as a cdi definition error.

 Agreed.


To sum up a recommendation I feel would do that:

- applications require @ApplicationScoped
- root level resources and providers require a scope; resources=@RequestScoped, providers=@ApplicationScoped
- 0 applications + n resources is interpreted as "default"; new Application() {}
- 1 application overrides "default"
- n applications raises CDI definition error??
- getClasses()
-- a class found to be existing annotated type (already discovered by CDI) must raise a definition error, otherwise it is added as an annotated type
-- resources=@RequestScoped
-- providers=@ApplicationScoped

 These semantics, although sound, are likely opposite of what most JAX-RS developers would expect. In a Servlet environment, the existence of an Application subclass takes precedence over any form of scanning/discovery. 
 
- getSingletons()
-- are "CDI unmanaged instances that are instantiated only once but that also support injection of dependencies"
-- I don't see why these should be added as beans because they may have been injected from beans…

 Probably better to deprecate/forbid getSingletons() altogether.

— Santiago


Derek Moore

unread,
Nov 18, 2018, 1:13:42 PM11/18/18
to Eclipse MicroProfile
Laird,

Check out the Hammock Project:

  https://github.com/hammock-project/hammock

It has some really neat ahead-of-specs CDI integrations. E.g., using CDI to enable swapping whole subsystem impls (Jersey vs. RestEasy vs. CXF; or Hibernate vs. EclipseLink vs. OpenJPA; or Jetty vs. Undertow vs. Tomcat; etc.). The JPA abstraction layer was written by the author of the CDI spec.

One place that I've found ill definition between JAX-RS & CDI is with subresource locators. I have to request subresource instances from CDI and then resourceCtx.initResource() those instances with JAX-RS in order to get all CDI annotations & JAX-RS annotations working together. It's a one-liner everywhere I want to return subresources (which I do a lot of the way I create MP Rest Client / WebResourceFactory client APIs), but I feel like it should be automatic instead of manual.

We could probably rope in the author of Jersey's CDI 2.0 integration if someone reached out to him (Petr Bouda <pbo...@ebay.com>). He has moved on from Oracle but is open to correspondence about Jersey & his work mapping Jersey/HK2 to CDI 2.0.

Derek

Laird Nelson

unread,
Nov 20, 2018, 3:51:57 PM11/20/18
to Eclipse MicroProfile
On Sunday, November 18, 2018 at 10:13:42 AM UTC-8, Derek Moore wrote:
Check out the Hammock Project:

  https://github.com/hammock-project/hammock

Hi, Derek; yes, I'm familiar with it.  John and I have very similar ideas.
 
One place that I've found ill definition between JAX-RS & CDI is with subresource locators. I have to request subresource instances from CDI and then resourceCtx.initResource() those instances with JAX-RS in order to get all CDI annotations & JAX-RS annotations working together. It's a one-liner everywhere I want to return subresources (which I do a lot of the way I create MP Rest Client / WebResourceFactory client APIs), but I feel like it should be automatic instead of manual.

Oh, that's an interesting use case.

Best,
Laird
Reply all
Reply to author
Forward
0 new messages