MP growing pains (rantish)

113 views
Skip to first unread message

Mark D. Anderson

unread,
Sep 23, 2019, 5:31:50 PM9/23/19
to Eclipse MicroProfile
Speaking as a frustrated user, and not a vendor, I would strongly push for ironing out
the many holes and infelicities in the initial core specs before adding any others.
I'm sure I'm getting some of the details wrong below, but here are some of the things
I've been battering my head against the past few weeks:

- Implementations differ, and apparently experts disagree, about what default scope JAX-RS
resources have without CDI. So since I do need to control that, I *have* to explicitly
have CDI2 annotations on all my resources, and @Path isn't enough. For example,
suppose I have an injected JsonWebToken or other member variable that is not application
scoped. Or suppose I don't want something instantiated on every request.

- Then suppose I want to get my actual application object injected, thank you very much,
and not some crippled proxy. So now I have to learn about the subtle difference
between @Singleton and @ApplicationScoped that somebody thought was a good idea, and
I have to use @Singleton in some places, or resort to vendor-specific unwrapping apis.

- So now I'm using 3 different DI annotations sets (@Context, CDI2, and CDI1) for
a basic REST service -- what is "Micro" about this?

- And I also have to experiment with how implementing or not implementing
getClasses() in my Application interacts with any CDI scanning, not to mention
some janky jandex incantations that might be done at build time, not run time.

- Oh and I have to be cognizant of the vital distinction between having no beans.xml
file and having an *empty* beans.xml file. Because even though there is a "Configuration" spec,
it doesn't include a clean way to configure Microprofile itself; instead I have to
engage in epimestological inquiries concerning the existence of "beans.xml".
In general, there is little consistency among MP implementations in how to control which MP services
I get. Some implementations use an external xml file.
Some do it based on feature "esa" dependencies. Some just control it based
solely on adding the provider dependency jars themselves.
MP itself does not articulate a standard way for me to configure which MP services I want,
let alone doing it using MP Configure.

- Now suppose I do want  to get "health" and "metrics'. Where are those endpoint urls
going to be? Is it /health or /contextroot/health or /contextroot/app-path/health ?
Who knows; each implementation seemingly does their own thing.
And if my contextroot is "" are those services still going to get routed?
What about access control? Are those MP services subject to the same filters (CORS etc)
and access control (including MP JWT Auth) as the main app?
Again, implementations vary. So now my monitoring and test scripts have to change
according to MP implementation.

- Speaking of JWT Auth, of course there is no standards-based way to supply the mandatory
configuration. Nor is there a clear standards-based way to express that a method requires
no authentication at all (vs @PermitAll which means authenticated but with no role requirement).
Nor is there clarity on what happens if a client still provides a bearer token to a method
not requiring one. Not to mention the fact that the "groups" claim may or may not correspond
to my @RolesAllowed annotations -- it says that a container must support a 1:1 group to role
mapping, but of course there is no articulation on how such policies are configured, nor
an API for how I might supply an alternative mapping.

- And is it too much to ask that the /openapi yaml/json content
has a "servers" section that represents where my app actually exists in that
very same container, including any contextroot?
So that consuming tools actually work out of the box?

- What if I might like to run multiple apps (microservices) in a single container?
Is that even supposed to work? Because J2EE and servlets each obviously support it.
But I wouldn't dream of trying that with MP.
Oh but maybe JDK 9+ modules might be part of the answer for multiple apps in a container?
Nice idea, but MP says nothing about that, and at the moment it seems that nearly every MP
implementation requires JDK8 to function reliably -- even though realistically anyone
adopting MP is going to want it to work with JDK11.

- Despite the increased interest in cloud/docker/k8 deployments, MP does not articulate
a golden path for deployable artifacts, akin to the "war" for servlet containers.
Most implementations have some kind of support for the abominable executable uber jars.
Some support thin jars. Some support thin wars.
Some use nothing at all, and we are expected to copy the whole build tree over somewhere.
But even though MP has a notion of a container, there is no expressed notion of what
file format it must support for the things it can contain.

In summary: despite the many "starter" projects, and intro tutorials out on the internet, I have
yet to manage to make my basic app work the same way across two implementations -- even
working at all has been a big challenge.

-mda

Siarhei Biarozkin

unread,
Sep 24, 2019, 6:29:23 AM9/24/19
to Eclipse MicroProfile
Hi Mark

Thanks for this feedback and let me add some comments about MP JWT:
I thought there was a standard way to configure either the inlined verification key content or the key location.
What is it that differs according to your experience ?
 
Nor is there a clear standards-based way to express that a method requires
no authentication at all (vs @PermitAll which means authenticated but with no role requirement).

I'm not sure supporting the semi-secured endpoints is the best way to bullet-protect the service. Letting the users having a single endpoint which authorizes POST requests and lets everyone GET on some method
will cause some issues for some users: someone will do a simple DB query, and a basic denial of service attack is just waiting to happen due to the excessive DB queries.
Nor is there clarity on what happens if a client still provides a bearer token to a method
not requiring one.

Same point here, IMHO it is worth restricting the spec in this regard :-)
Not to mention the fact that the "groups" claim may or may not correspond
to my @RolesAllowed annotations -- it says that a container must support a 1:1 group to role
mapping, but of course there is no articulation on how such policies are configured, nor
an API for how I might supply an alternative mapping.

Indeed, it is not too flexible, but the issue already exists to support the tokens which have the groups/roles info in the other claims.
In our implementation we are letting users point to a custom claim containing an array of roles (or single value with the comma-separated roles) using a hierarchical path property.
Do you think it should be supported at the MP JWT level ? Please open an issue if yes; if you have some ideas in mind - please open an issue too :-), and we'll all continue the discussions there

Thanks Sergey

Ken Finnigan

unread,
Sep 24, 2019, 2:46:34 PM9/24/19
to MicroProfile
Mark,

Thanks for taking the time to provide your feedback on MicroProfile. I've provided comments inline below

Ken

On Mon, Sep 23, 2019 at 5:31 PM Mark D. Anderson <m...@discerning.com> wrote:
Speaking as a frustrated user, and not a vendor, I would strongly push for ironing out
the many holes and infelicities in the initial core specs before adding any others.
I'm sure I'm getting some of the details wrong below, but here are some of the things
I've been battering my head against the past few weeks:

- Implementations differ, and apparently experts disagree, about what default scope JAX-RS
resources have without CDI. So since I do need to control that, I *have* to explicitly
have CDI2 annotations on all my resources, and @Path isn't enough. For example,
suppose I have an injected JsonWebToken or other member variable that is not application
scoped. Or suppose I don't want something instantiated on every request.

As MicroProfile has CDI as a base, what happens when CDI is not present is not in the current remit of what MicroProfile attempts to cover.

Having said that, I know there is some vagueness around how JAX-RS defines the "request lifecycle" and what that translates to in CDI.
There's been a long-debated issue on this topic (https://github.com/eclipse/microprofile/issues/50), with the current consensus being that the community
did not want to break backward compatibility with Java EE/Jakarta EE.
 

- Then suppose I want to get my actual application object injected, thank you very much,
and not some crippled proxy. So now I have to learn about the subtle difference
between @Singleton and @ApplicationScoped that somebody thought was a good idea, and
I have to use @Singleton in some places, or resort to vendor-specific unwrapping apis.

The need to understand when an object is proxied and when it isn't is necessary not just for MicroProfile.
CDI is part of Java EE and Jakarta EE, as such, they would also encounter the problem you describe.

Aside from that, why do you need to know whether the object is actually a proxy or not to use it?

What does the code do that requires access to the underlying class?
 

- So now I'm using 3 different DI annotations sets (@Context, CDI2, and CDI1) for
a basic REST service -- what is "Micro" about this?

Once again, this is inherited from Java EE/Jakarta EE.

My understanding is that JAX-RS in future versions is looking to fully embrace the CDI programming model,
which may retire the need for @Context.

Why would you need CDI1 and CDI2 dependencies to be present? CDI2 is backward compatible with CDI1


- And I also have to experiment with how implementing or not implementing
getClasses() in my Application interacts with any CDI scanning, not to mention
some janky jandex incantations that might be done at build time, not run time.

If you want your classes to use the JAX-RS lifecycle return them in getClasses().

If you want your classes managed by CDI, don't return them in getClasses() and ensure they have an appropriate scope annotation on them.
 

- Oh and I have to be cognizant of the vital distinction between having no beans.xml
file and having an *empty* beans.xml file. Because even though there is a "Configuration" spec,
it doesn't include a clean way to configure Microprofile itself; instead I have to
engage in epimestological inquiries concerning the existence of "beans.xml".

Presence or not of beans.xml and MP Config spec are completely unrelated.

beans.xml is a requirement of CDI, not of MP Config.

It could be interesting to see if it's possible to provide MP Config settings that equate to a beans.xml, and therefore negate the need for it. If that's something you'd like to see please raise an issue: https://github.com/eclipse/microprofile/issues
 
In general, there is little consistency among MP implementations in how to control which MP services
I get. Some implementations use an external xml file.
Some do it based on feature "esa" dependencies. Some just control it based
solely on adding the provider dependency jars themselves.
MP itself does not articulate a standard way for me to configure which MP services I want,
let alone doing it using MP Configure.

One of the reasons MicroProfile hasn't defined anything around this, or packaging and deployment definitions, is because there are many ways that this can be achieved across different implementations. Trying to define a specification that caters to all the variants that implementations currently support would make such a specification extremely difficult and likely unworkable.

MicroProfile aims for API and knowledge portability, not entire application portability.
 

- Now suppose I do want  to get "health" and "metrics'. Where are those endpoint urls
going to be? Is it /health or /contextroot/health or /contextroot/app-path/health ?
Who knows; each implementation seemingly does their own thing.
And if my contextroot is "" are those services still going to get routed?
What about access control? Are those MP services subject to the same filters (CORS etc)
and access control (including MP JWT Auth) as the main app?
Again, implementations vary. So now my monitoring and test scripts have to change
according to MP implementation.

Implementations shouldn't be doing their own thing when it comes to where those endpoints are exposed, at least for them to be considered MicroProfile compatible.
If there are implementations where this is not the case, then please raise that issue with the implementations.

Both the Health and Metrics specifications define the endpoints that must be provided, though most runtimes offer the ability to customize the endpoint they can be accessed from.

Granted what that endpoint exactly is might differ depending on the deployment model. For instance, Thorntail would have the endpoints available at /health and /metrics because there is only a single context root, whereas Open Liberty would have them on /contextroot/health and /contextroot/metrics.

Now maybe any specification defining an endpoint needs to be clearer about the situations you've described if you consider them to be lacking. If so, please file issues on the respective projects to have the specification document clarified.
 

- Speaking of JWT Auth, of course there is no standards-based way to supply the mandatory
configuration. Nor is there a clear standards-based way to express that a method requires
no authentication at all (vs @PermitAll which means authenticated but with no role requirement).
Nor is there clarity on what happens if a client still provides a bearer token to a method
not requiring one. Not to mention the fact that the "groups" claim may or may not correspond
to my @RolesAllowed annotations -- it says that a container must support a 1:1 group to role
mapping, but of course there is no articulation on how such policies are configured, nor
an API for how I might supply an alternative mapping.


I'm not very familiar with the intricacies of JWT. However, please raise any issues if you see there being areas that can be clarified or improved.
 
- And is it too much to ask that the /openapi yaml/json content
has a "servers" section that represents where my app actually exists in that
very same container, including any contextroot?
So that consuming tools actually work out of the box?

Would you expect this to be auto-created or have it provided via a config property?

I ask because in container environments the particular container doesn't usually have access to, or know, what the URL is that it's being exposed under.
 

- What if I might like to run multiple apps (microservices) in a single container?
Is that even supposed to work? Because J2EE and servlets each obviously support it.
But I wouldn't dream of trying that with MP.

MicroProfile, by design, does not support the idea of multiple deployments to a single instance.
That's not to say that it might work anyway, depending on the implementation, but the intention was to focus on cloud-native and microservice development where it's the norm for there to be a single application per instance.
 
Oh but maybe JDK 9+ modules might be part of the answer for multiple apps in a container?
Nice idea, but MP says nothing about that, and at the moment it seems that nearly every MP
implementation requires JDK8 to function reliably -- even though realistically anyone
adopting MP is going to want it to work with JDK11.

We're currently in the process of verifying that all MP specifications, TCKs, and implementations can run on JDK 11. Once we've verified that with a sufficient number of implementations, then we will announce that MicroProfile beyond a particular release is supported on JDK 11.

As for JPMS, my understanding is that it's good for managing modules within the JDK but likely not something you want for your application.
 

- Despite the increased interest in cloud/docker/k8 deployments, MP does not articulate
a golden path for deployable artifacts, akin to the "war" for servlet containers.
Most implementations have some kind of support for the abominable executable uber jars.
Some support thin jars. Some support thin wars.
Some use nothing at all, and we are expected to copy the whole build tree over somewhere.
But even though MP has a notion of a container, there is no expressed notion of what
file format it must support for the things it can contain.

As mentioned previously, MicroProfile doesn't define packaging or deployment specifications because implementations have many different ways to achieve it.

Now maybe we need to think about defining what a "container deployment" should look like, to at least provide some commonality there, while not precluding other deployment types.
 

In summary: despite the many "starter" projects, and intro tutorials out on the internet, I have
yet to manage to make my basic app work the same way across two implementations -- even
working at all has been a big challenge.

Without input and contributions from users such as yourself, there is absolutely no way for MicroProfile to improve and actually help to solve the problems of users. To that end, I would ask that you take the time to raise issues in GitHub to tackle the problems you've found and described.
 

-mda

--
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 view this discussion on the web visit https://groups.google.com/d/msgid/microprofile/425ae273-24d9-4ff4-b955-389e09620a70%40googlegroups.com.

Mark D. Anderson

unread,
Sep 25, 2019, 12:04:25 PM9/25/19
to microp...@googlegroups.com
Thank you to both Ken and Sirhei for your considered replies.
(and sorry in advance for "top posting"....)

Regarding CDI and my Application subclass -- perhaps this was a self-induced rathole, but
to be clear on how I got there.... I was thinking "Oh hey, my Application subclass is a ready-
made singleton that is super convenient,  let me put some more extra useful methods and
variables in it, and then inject it into my Resource subclasses".   And then discovered I was not getting my actual
instance and couldn't call my new methods on it. So that is how I ventured into @Singleton
(CDI1) because that doesn't play games with proxies.
But I'm thinking now that it was all "Wrong Think" and I shouldn't have been putting any extra
stuff in the Application subclass, and should have made a separate singleton, and injecting
that separate singleton (without all the baggage of Application) with CDI2 should work just fine.

As for how to get things activated and with desired scope. Consider this logic table:

   resource class (@Path) has CDI2 scope annotation
        Application subclass (@ApplicationPath) has CDI2 scope annotation
            Application subclass implements getClasses
                 beans.xml file
                                  result
   N   N  N  -               JAX-RS runtime will find them, but with indeterminate scope
   Y    N  Y  empty      JAX-RS will find app and getClasses() will override anything found by CDI2?
    ....
   Y    Y  N  empty       CDI2 finds resources and providers, and scope is explicit

with many other potential rows in the table. I'm really not sure what the result column is supposed
to be in theory, and in practice I see a fair amount of variability.
So I end up doing the last row just to be extra "pinky sure". But I'd rather not have to have
both @Path and @*Scoped everywhere.

But that is just for *my* stuff. What about the MP services or other non-standard providers that
come with my MP container?
I haven't found any portable way to control them, either via white list or black list.
I can't white list them in my getClasses(), because that wouldn't be portable.
(Jersey ResourceConfig has packages(String) but that isn't portable, and anyway I 
would have to track down all the packages/classes that each MP is using.)
There is nothing in MP Config that seems to control it either.
Instead, for "build up" containers like Quarkus, the selection is based on what dependencies
I pull. For "cut down" containers like Liberty, I would need to select based on a <features> element
in some non-portable xml file.

And then what about black listing? Most of the MP implementations include some sort of CORS filter and an
exception filter, but IMHO these are typically poorly documented, not very configurable, and
don't do what I want out of the box. So then I want to disable these "builtin" Providers and
just use my own.

Regarding the endpoints for MP services, Ken says
    "Both the Health and Metrics specifications define the endpoints that must be provided"
So who is wrong? Is it TomEE at /contextroot/apppath/health, or is it Liberty at /health ?
And are those endpoints like /health and /metrics supposed to be subject to the same
JWT Auth access control provisions as my app ?
How about all my other filter Providers?

Regarding /openapi/ui my point is that the builtin swagger ui is in general not going to be
able to successfully call my service (in the same container!) nor will any external tool, because
the yaml generated and returned at /openapi (assuming i didn't hard code it, but used openapi 
annotations) will typically not have any "servers" in it.
Any container at runtime *totally* knows all routes. 
I know some MP containers generate the openapi.* files at build time, and some at runtime.
I know I don't want to hard-code the absolute path to my server in Java code.
But so far I haven't found any way to automatically get an /openapi yaml to have a servers section that
corresponds to what that container *knows* about the route to my app in that same server.
Instead I've been forced to hardcode my deployment context root in Java code
with @OpenAPIDefinition (servers = @Server(url = "/contextroot/apppath"))

As for format of deployable artifacts, I appreciate that there are scope issues in how much
MP wants to bite off.  I do get frustrated that all the MP implementations out-of-the-box 
seem oriented around uber jar abominations, which are not what I want to put into Docker.
But I guess that is more of what an vendor-specific issue.


-mda

Laird Nelson

unread,
Sep 25, 2019, 1:31:18 PM9/25/19
to Eclipse MicroProfile
On Wednesday, September 25, 2019 at 9:04:25 AM UTC-7, Mark D. Anderson wrote:
I do get frustrated that all the MP implementations out-of-the-box 
seem oriented around uber jar abominations, which are not what I want to put into Docker.

A small data point: Helidon's MicroProfile implementation does not use this strategy.  You can see what it does here: https://helidon.io/docs/latest/#/guides/03_quickstart-mp

Best,
Laird

Ken Finnigan

unread,
Sep 25, 2019, 1:34:03 PM9/25/19
to MicroProfile
Maybe it's just me, but the table you have there makes sense. It doesn't mean it's perfect though.

What the table has described indicates that classes defined in getClasses() are managed by JAX-RS,
and when there's a CDI Scope annotation it's managed by CDI.

Sure it's not ideal that you need @Path and CDI Scope annotations to have a JAX-RS Resource class use the CDI Lifecycle,
but that's how it's currently mandated by the JAX-RS specification. As mentioned previously, maybe future versions of JAX-RS
can provide tighter integration with CDI and remove this duality, but that's up to the community involved in that specification to request such a change.
 

But that is just for *my* stuff. What about the MP services or other non-standard providers that
come with my MP container?
I haven't found any portable way to control them, either via white list or black list.
I can't white list them in my getClasses(), because that wouldn't be portable.
(Jersey ResourceConfig has packages(String) but that isn't portable, and anyway I 
would have to track down all the packages/classes that each MP is using.)
There is nothing in MP Config that seems to control it either.
Instead, for "build up" containers like Quarkus, the selection is based on what dependencies
I pull. For "cut down" containers like Liberty, I would need to select based on a <features> element
in some non-portable xml file.

What exactly are you looking to control with respect to MP services? Their presence in an application or something else?

As mentioned previously, depending on what you want to control, there are so many different ways this can be done by implementors
it's very difficult to define a specification as to how it should work in a portable manner.
 

And then what about black listing? Most of the MP implementations include some sort of CORS filter and an
exception filter, but IMHO these are typically poorly documented, not very configurable, and
don't do what I want out of the box. So then I want to disable these "builtin" Providers and
just use my own.

Currently, there are no CORS filters defined by an MP specification, and there is only an exception filter for MP REST Client.

Any other filters are either defined by Java EE specifications that MP has in its base, or it's part of a specific implementation.

If you'd like to see some of these aspects defined in a more common way, please raise issues and put forth your ideas about what should be specified in addition to what is done today.
 

Regarding the endpoints for MP services, Ken says
    "Both the Health and Metrics specifications define the endpoints that must be provided"
So who is wrong? Is it TomEE at /contextroot/apppath/health, or is it Liberty at /health ?

I'm not familiar with exactly what endpoints other implementations might have for health or metrics, so I am not able to comment specifically on what the issues might be.

However, if it's sufficiently unclear as to what endpoints should be, then it should be clarified within the specifications.
 
And are those endpoints like /health and /metrics supposed to be subject to the same
JWT Auth access control provisions as my app ? 
How about all my other filter Providers?

I don't believe any specification that defines an endpoint has indicated requirements around securing them, presently it's assumed to be a task for the developer if they want them secured,
or whether other filters should operate on those endpoints.

If that's a gap that needs filling, then please raise an issue in the respective GitHub repositories so that it can be resolved. Or even open an issue at the main project as it touches on several specifications, it might require a more architectural discussion as to the correct approach.
 

Regarding /openapi/ui my point is that the builtin swagger ui is in general not going to be
able to successfully call my service (in the same container!) nor will any external tool, because
the yaml generated and returned at /openapi (assuming i didn't hard code it, but used openapi 
annotations) will typically not have any "servers" in it.
Any container at runtime *totally* knows all routes. 

Can you clarify your statement here?

My understanding of an environment such as Kubernetes is that the container running an application instance only knows the IP address of itself. The container has no idea about what URLs it may be exposed on, as it could be Kubernetes Routes or Istio Ingress Routes.

From discussions with those that are part of the OpenAPI specification work, it's been suggested that a static OpenAPI file containing the servers list is provided to the application runtime so that it can be merged with the annotation-based model.
 
I know some MP containers generate the openapi.* files at build time, and some at runtime.
I know I don't want to hard-code the absolute path to my server in Java code.
But so far I haven't found any way to automatically get an /openapi yaml to have a servers section that
corresponds to what that container *knows* about the route to my app in that same server.
Instead I've been forced to hardcode my deployment context root in Java code
with @OpenAPIDefinition (servers = @Server(url = "/contextroot/apppath"))

As for format of deployable artifacts, I appreciate that there are scope issues in how much
MP wants to bite off.  I do get frustrated that all the MP implementations out-of-the-box 
seem oriented around uber jar abominations, which are not what I want to put into Docker.

I know it's not the case that all MP implementations take an uber jar approach to packaging. Quarkus provides the ability to create Docker images whereby the dependent libs are in one layer and the application code is in its own layer.
 

John Clingan

unread,
Sep 25, 2019, 2:50:24 PM9/25/19
to microp...@googlegroups.com

Ken, I disagree with "MicroProfile aims for API and knowledge portability, not entire application portability.". We want application portability as much as possible within a MicroProfile [insert spec name] version. The caveat is that not all MicroProfile implementations support all specifications, which is part of the growing pain discussions.

Mark, and I'm agreeing with Ken here, specifications are about application portability. Defining application build/packaging are outside the scope of specs to give flexibility in how vendors implement the specs.  It is fair to opine that a pom.xml file, xml config file, etc, can be considered application code, and it's a fair opinion the other way around. However, not formalizing this is via a specification is a tradeoff that MicroProfile (and Jakarta EE / Java EE) makes.

On Tuesday, September 24, 2019 at 11:46:34 AM UTC-7, Ken Finnigan wrote:
<SNIP>
 
In general, there is little consistency among MP implementations in how to control which MP services
I get. Some implementations use an external xml file.
Some do it based on feature "esa" dependencies. Some just control it based
solely on adding the provider dependency jars themselves.
MP itself does not articulate a standard way for me to configure which MP services I want,
let alone doing it using MP Configure.

One of the reasons MicroProfile hasn't defined anything around this, or packaging and deployment definitions, is because there are many ways that this can be achieved across different implementations. Trying to define a specification that caters to all the variants that implementations currently support would make such a specification extremely difficult and likely unworkable.

MicroProfile aims for API and knowledge portability, not entire application portability.
 </SNIP
 

Ken Finnigan

unread,
Sep 25, 2019, 2:55:30 PM9/25/19
to MicroProfile
I'd split some hairs and say MP is going for "application source portability".

I say that because you can't build a Thorntail uber jar and deploy it to OpenLiberty, at least I doubt it, and I wouldn't expect that to be possible with MicroProfile. So a "built" application will not be portable, but the "source" should be.

On Wed, Sep 25, 2019 at 2:50 PM John Clingan <jcli...@redhat.com> wrote:

Ken, I disagree with "MicroProfile aims for API and knowledge portability, not entire application portability.". We want application portability as much as possible within a MicroProfile [insert spec name] version. The caveat is that not all MicroProfile implementations support all specifications, which is part of the growing pain discussions.

Mark, and I'm agreeing with Ken here, specifications are about application portability. Defining application build/packaging are outside the scope of specs to give flexibility in how vendors implement the specs.  It is fair to opine that a pom.xml file, xml config file, etc, can be considered application code, and it's a fair opinion the other way around. However, not formalizing this is via a specification a tradeoff that MicroProfile (and Jakarta EE / Java EE) makes.

On Tuesday, September 24, 2019 at 11:46:34 AM UTC-7, Ken Finnigan wrote:
<SNIP>
 
In general, there is little consistency among MP implementations in how to control which MP services
I get. Some implementations use an external xml file.
Some do it based on feature "esa" dependencies. Some just control it based
solely on adding the provider dependency jars themselves.
MP itself does not articulate a standard way for me to configure which MP services I want,
let alone doing it using MP Configure.

One of the reasons MicroProfile hasn't defined anything around this, or packaging and deployment definitions, is because there are many ways that this can be achieved across different implementations. Trying to define a specification that caters to all the variants that implementations currently support would make such a specification extremely difficult and likely unworkable.

MicroProfile aims for API and knowledge portability, not entire application portability.
 </SNIP
 

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

John Clingan

unread,
Sep 25, 2019, 3:01:44 PM9/25/19
to Eclipse MicroProfile
Regarding different health endpoints, here is the relevant spec text:
"These endpoints are expected to be associated with a configurable context, such as a web application deployment, that can be configured with settings such as port, virtual-host, security, etc."

In other words, the behavior you are seeing is as expected. Now, you as a user seeing this as a negative experience is valuable feedback. It would be really helpful to continue to communicate here and perhaps join a MicroProfile Health call to see if this should change. Note that a change you desire, if approved, is a breaking change and would have to wait until a major new spec version release.


On Wednesday, September 25, 2019 at 9:04:25 AM UTC-7, Mark D. Anderson wrote:
To unsubscribe from this group and stop receiving emails from it, send an email to microprofile+unsubscribe@googlegroups.com.


--
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+unsubscribe@googlegroups.com.

John Clingan

unread,
Sep 25, 2019, 3:03:25 PM9/25/19
to Eclipse MicroProfile
Quarkus and Helidon take similar approaches, IIRC. Lightweight application jar w/metadata pointing to lib/*.jar files.

John Clingan

unread,
Sep 25, 2019, 3:05:03 PM9/25/19
to Eclipse MicroProfile
OK, yeah, I agree 100% with that. What you describe falls under "implementation detail".
To unsubscribe from this group and stop receiving emails from it, send an email to microprofile+unsubscribe@googlegroups.com.

Arjan Tijms

unread,
Sep 25, 2019, 3:30:17 PM9/25/19
to Eclipse MicroProfile
Hi,


On Monday, September 23, 2019 at 11:31:50 PM UTC+2, Mark D. Anderson wrote:
- Speaking of JWT Auth, of course there is no standards-based way to supply the mandatory
configuration.


 
Nor is there a clear standards-based way to express that a method requires
no authentication at all (vs @PermitAll which means authenticated but with no role requirement).

@PermitAll is a bit confusing. Its Javadoc first speaks of "all security roles", but then clarifies by saying it's "unchecked".

Unchecked means no check at all, i.e. free to everyone to access, authenticated or not.

See 


Authenticated, but no role requirement, is expressed via the "any authenticated" pseudo-role "**"

See

No authentication at all would typically be expressed by simply not annotating the JAX-RS method with an @RolesAllowed, although if you want to override class level behaviour then @PermitAll can be used.

This is defined in the JWT spec in 7.3:

7.3. Using the Common Security Annotations for the Java Platform (JSR-250)
The expectations for use of the various security annotations described in sections 2.9 - 2.12 of JSR- 250 (@RolesAllowed, @PermitAll, @DenyAll), is that MP-JWT containers support the behavior as described in those sections. In particular, the interaction between the annotations should be as described in section 2.12 of JSR-250.

I remember handling it in my implementation, but tbh I'm not sure if the actual method level overrides are tested in the TCK, and glancing at my code it might indeed not:


 
Nor is there clarity on what happens if a client still provides a bearer token to a method
not requiring one.

The issue here is that JWT Auth primarily defines an authentication mechanism, and somewhat adhoc assumes there's an underlying implied (but not specified) security system. Had JWT Auth simply depended on Java EE/Jakarta EE security this would have been far less of an issue, or no issue at all (but at the time this was not possible, as MP was based on EE 7).

The problem here is that while JWT is only supposed to be an authentication mechanism, you quickly do get into details such as you mentioned. For that JWT would have to increasingly define this implied security system, eventually pretty much duplicating Java EE/Jakarta EE Security. This is a problem with @RolesAllowed/DenyAll/PermitAll as well. These annotations should not be solely defined to be applicable to JAX-RS methods in JWT Auth, but should be in JAX-RS and/or Jakarta Security. Those TCKs can exhaustively test all combinations, for all sorts of authentication mechanisms, not just JWT.

Fyi though, this exact point about pre-emptive authentication was being brought up during one of the JWT meetings.

 
Not to mention the fact that the "groups" claim may or may not correspond
to my @RolesAllowed annotations -- it says that a container must support a 1:1 group to role
mapping, but of course there is no articulation on how such policies are configured, nor
an API for how I might supply an alternative mapping.

Indeed. This partially comes back again to this dependency on the implied security system. I say partially, since even the standard Java/Jakarta Security system hasn't really standardised this and depends on the facilities of the underlying container. See step 7 here for examples for various containers:


The plan is to, finally, standardise group to role mapping for Jakarta EE Security.Next, but for MicroProfile this will only really help if MP formally depends on that (practically speaking Payara and SmallRye already depend on it).

Kind regards,
Arjan Tijms

Mark D. Anderson

unread,
Sep 29, 2019, 11:29:33 PM9/29/19
to microp...@googlegroups.com
Hi Arjan -

Thanks for your reply regarding JWT stuff

On Wed, Sep 25, 2019, at 12:30 PM, Arjan Tijms wrote:
Hi,

On Monday, September 23, 2019 at 11:31:50 PM UTC+2, Mark D. Anderson wrote:
- Speaking of JWT Auth, of course there is no standards-based way to supply the mandatory
configuration.

Are you sure you looked at JWT 1.1?

The first version indeed missed this, but we added this in 1.1.

Yes I think i was looking at the older spec. Probably because the various blog tutorials that the google finds
are behind latest specs.



See this example:


vs


 
Nor is there a clear standards-based way to express that a method requires
no authentication at all (vs @PermitAll which means authenticated but with no role requirement).

@PermitAll is a bit confusing. Its Javadoc first speaks of "all security roles", but then clarifies by saying it's "unchecked".

Unchecked means no check at all, i.e. free to everyone to access, authenticated or not.

I've found multiple opinions on the net, including these that say quite clearly that (in their opinion) PermitAll requires successful authentication:

JSR250 says in part:

    The PermitAll annotation specifies that all security roles are allowed to invoke the specified method(s), that is, that the specified method(s) are “unchecked”. 
     ....
    The PermitAll, DenyAll and RolesAllowed annotations all define which security roles are allowed to access the methods on which they are applied. 

So i think it comes down to whether "all security roles" includes none at all (because unauthenticated).

There is zero use of @PermitAll in any of the java files in microprofile1.*-samples
So I'm not sure what those samples would be able to show.
Is there some standard supporting * as the "any authenticated" role?
Because if so, then that would be convincing evidence that PermitAll includes the unauthenticated state,
because otherwise it would have the same meaning as "*".


See

No authentication at all would typically be expressed by simply not annotating the JAX-RS method with an @RolesAllowed, although if you want to override class level behaviour then @PermitAll can be used.


That is *exactly* what I want to do -- have a class level @RolesAllowed, with a @PermitAll on a few methods
which would mean "authenticated or unauthenticated, i don't care".
But I guess I'm still not convinced that the MP specs support this interpretation.

-mda


This is defined in the JWT spec in 7.3:

7.3. Using the Common Security Annotations for the Java Platform (JSR-250)
The expectations for use of the various security annotations described in sections 2.9 - 2.12 of JSR- 250 (@RolesAllowed, @PermitAll, @DenyAll), is that MP-JWT containers support the behavior as described in those sections. In particular, the interaction between the annotations should be as described in section 2.12 of JSR-250.

I remember handling it in my implementation, but tbh I'm not sure if the actual method level overrides are tested in the TCK, and glancing at my code it might indeed not:


 
Nor is there clarity on what happens if a client still provides a bearer token to a method
not requiring one.

The issue here is that JWT Auth primarily defines an authentication mechanism, and somewhat adhoc assumes there's an underlying implied (but not specified) security system. Had JWT Auth simply depended on Java EE/Jakarta EE security this would have been far less of an issue, or no issue at all (but at the time this was not possible, as MP was based on EE 7).

The problem here is that while JWT is only supposed to be an authentication mechanism, you quickly do get into details such as you mentioned. For that JWT would have to increasingly define this implied security system, eventually pretty much duplicating Java EE/Jakarta EE Security. This is a problem with @RolesAllowed/DenyAll/PermitAll as well. These annotations should not be solely defined to be applicable to JAX-RS methods in JWT Auth, but should be in JAX-RS and/or Jakarta Security. Those TCKs can exhaustively test all combinations, for all sorts of authentication mechanisms, not just JWT.

Fyi though, this exact point about pre-emptive authentication was being brought up during one of the JWT meetings.

 
Not to mention the fact that the "groups" claim may or may not correspond
to my @RolesAllowed annotations -- it says that a container must support a 1:1 group to role
mapping, but of course there is no articulation on how such policies are configured, nor
an API for how I might supply an alternative mapping.

Indeed. This partially comes back again to this dependency on the implied security system. I say partially, since even the standard Java/Jakarta Security system hasn't really standardised this and depends on the facilities of the underlying container. See step 7 here for examples for various containers:


The plan is to, finally, standardise group to role mapping for Jakarta EE Security.Next, but for MicroProfile this will only really help if MP formally depends on that (practically speaking Payara and SmallRye already depend on it).

Kind regards,
Arjan Tijms


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

Mark D. Anderson

unread,
Sep 29, 2019, 11:56:44 PM9/29/19
to microp...@googlegroups.com


On Wed, Sep 25, 2019, at 12:01 PM, John Clingan wrote:
Regarding different health endpoints, here is the relevant spec text:
"These endpoints are expected to be associated with a configurable context, such as a web application deployment, that can be configured with settings such as port, virtual-host, security, etc."

In other words, the behavior you are seeing is as expected. Now, you as a user seeing this as a negative experience is valuable feedback. It would be really helpful to continue to communicate here and perhaps join a MicroProfile Health call to see if this should change. Note that a change you desire, if approved, is a breaking change and would have to wait until a major new spec version release.


I totally get that the base url (including a context root) is a deployment time issue, and the same application
bits might be deployed to different base urls.

What I *don't* get is why there is  (as far as I can see) wishy-washiness about whether /health
and /metrics are absolute paths (potentially above context root), or relative to context root, or
relative to application path.

Insofar as "health" and "metrics' (and "openapi") are all intimately tied to *exactly* one application (as
annotated by @ApplicationPath), then I would generally expect that one would have these endpoint urls:

   ....

That way, in those containers that support hosting multiple applications, each one gets
their own contextroot and they won't interfere with each other (which they would as absolute paths).

Except.... what about the case of no Application, or @ApplicationPath("") ?
Then we would have:


and then we do have the potential for someone using @Path("health") and getting a conflict.
But maybe that is ok.

What is bothering me, from a testing and monitoring point of view, is that if I deploy to different MP vendors,
right now I believe I need to know more than just the baseurl for deployment; I need to have vendor-specific
adjustments for where they chose to map the extra service resources like health and metrics.
That is, I want more than "application portability"; I want "application plus exposed MP services" portability.

Also, to be clear, i was hoping that the different MP specs would synergize so that the whole is greater than the parts.
So for example, there would be a standardized way on how i might use MP Config + MP JWT to specify what roles
would be permitted to access metrics.

-mda


To unsubscribe from this group and stop receiving emails from it, send an email to microprofile...@googlegroups.com.

Mark D. Anderson

unread,
Sep 30, 2019, 12:49:05 AM9/30/19
to microp...@googlegroups.com
I sure hope so. Because I would love it if the simple case of just using @Path would get me something 
besides the who-knows-what-will-happen lifecycle scope.

I think all that would need to happen is to clearly say that the unspecified scope in MP JAX-RS is always
X (X being RequestScoped or ApplicationScoped -- I don't know what the decision would be, i just want it known).
I understand though that there are standardization difficulties for any spec shared between MP and JEE.

 


But that is just for *my* stuff. What about the MP services or other non-standard providers that
come with my MP container?
I haven't found any portable way to control them, either via white list or black list.
I can't white list them in my getClasses(), because that wouldn't be portable.
(Jersey ResourceConfig has packages(String) but that isn't portable, and anyway I 
would have to track down all the packages/classes that each MP is using.)
There is nothing in MP Config that seems to control it either.
Instead, for "build up" containers like Quarkus, the selection is based on what dependencies
I pull. For "cut down" containers like Liberty, I would need to select based on a <features> element
in some non-portable xml file.

What exactly are you looking to control with respect to MP services? Their presence in an application or something else?


To start with yes -- just being able to whitelist and/or blacklist services.
So for example, i might be able to say using MP Config:
       mp.health.path=health   # context-root relative
       mp.health.rolesallowed=*    # must be authenticated
       mp.metrics.enabled=false   # disable this service
 
Now maybe in part the answer to what I'm looking for can be achieved by using beans.xml with some
verbose xml involving "exclude" "if-class-not-available" etc..... but in general, the various MP services
like "health" and "metrics" are not going to be in the same "bean archive" as my app, right?
So I can't do it that way.

And AFAIK there is no easy way for example for me to disable any and all providers with "CORS" or "Cors"
in their name, because I've got my own provider for that, thank you very much.

I guess what I'm hearing is that me controlling non-MP providers (such as CORS filters, or exception
filters etc) is out of scope for MP standardization, so I just have to dig through for each vendor's container
how to hamstring them.

However, is it also out of scope for an application to somehow express in a standard way
(via MP Config and/or annotations) which MP services it would like?
Oh it is definitely the case that it has no visibility about upstream url rewriting.
But once the web container is hit (and I mean the java server, not the Docker container), it definitely
knows all routes it needs to support.
It knows whether it has a handler for "/health" or for "/somecontext/health" or "/somecontext/apppath/health"

And my point is that it is disingenuous to say that the java server has no way of knowing, in its openapi handler,
what the path is to the app hosted by itself.

Sure, it is often the case that openapi documentation might be hosted on some completely different server
from the production or qa servers that actually provide the services.
I'm just looking for a "least surprises" behavior when /openapi/ui and /myapp are hosted in the same jvm. 


From discussions with those that are part of the OpenAPI specification work, it's been suggested that a static OpenAPI file containing the servers list is provided to the application runtime so that it can be merged with the annotation-based model.

IMHO ideal would be support for some kind of hybrid merger of dynamically generated (from @OpenAPI) and
statically provided. I can do a few things with @OpenAPIDefinition but ideally I'd like to, at build time, based on
a profile, pull in my choice from a variety of external yaml/json api spec fragments.

 

I know some MP containers generate the openapi.* files at build time, and some at runtime.
I know I don't want to hard-code the absolute path to my server in Java code.
But so far I haven't found any way to automatically get an /openapi yaml to have a servers section that
corresponds to what that container *knows* about the route to my app in that same server.
Instead I've been forced to hardcode my deployment context root in Java code
with @OpenAPIDefinition (servers = @Server(url = "/contextroot/apppath"))

As for format of deployable artifacts, I appreciate that there are scope issues in how much
MP wants to bite off.  I do get frustrated that all the MP implementations out-of-the-box 
seem oriented around uber jar abominations, which are not what I want to put into Docker.

I know it's not the case that all MP implementations take an uber jar approach to packaging. Quarkus provides the ability to create Docker images whereby the dependent libs are in one layer and the application code is in its own layer.

I like many of the things I see in Quarkus, but I've been unable to get it to work above jdk8, so it was a nonstarter.
When the dust settles on 0.23 i will give it another spin.

-mda

Arjan Tijms

unread,
Sep 30, 2019, 6:01:21 AM9/30/19
to Eclipse MicroProfile


On Monday, September 30, 2019 at 5:29:33 AM UTC+2, Mark D. Anderson wrote:

I've found multiple opinions on the net, including these that say quite clearly that (in their opinion) PermitAll requires successful authentication:

JSR250 says in part:

    The PermitAll annotation specifies that all security roles are allowed to invoke the specified method(s), that is, that the specified method(s) are “unchecked”. 
     ....
    The PermitAll, DenyAll and RolesAllowed annotations all define which security roles are allowed to access the methods on which they are applied. 

So i think it comes down to whether "all security roles" includes none at all (because unauthenticated).

It includes the "unauthenticated security role", which is somewhat confusing as mentioned earlier. Essentially the unauthenticated security role is assigned when either authentication has not been done at all, or authentication has been attempted, but the authentication module decided to do nothing.

In Servlet Containers the representation of the unauthenticated caller *principal* is simply null, and just its name is null as well. In EJB the unauthenticated caller principal name is defaulted to "something", which is highly annoying. E.g. it can be set to "ANONYMOUS".

EJB is the only specification in Java EE that officially interprets @DenyAll.

EJB 12.3.2.1 says about this:

" The PermitAll annotation specifies that all security roles, including any unauthenticated roles, are permitted to execute the specified method(s). "

Notice the phrasing "including any unauthenticated roles".

 
There is zero use of @PermitAll in any of the java files in microprofile1.*-samples
So I'm not sure what those samples would be able to show.


That one shows how to setup (configure) MP JWT without having to resort to vendor specific configuration. I referred to that example before the quote about @PermitAll.

 
Is there some standard supporting * as the "any authenticated" role?
Because if so, then that would be convincing evidence that PermitAll includes the unauthenticated state,
because otherwise it would have the same meaning as "*".

Well "**" was primarily defined in the JACC spec, and from there copied into Servlet and EJB. "*" was primarily specified in the Servlet spec. Things would have been a tad simpler if those specs just directly referenced JACC for their behaviour, and JACC was the foundation of it all, but alas.

There are some holes, still, though.

Servlet 13.8 says:

"The special role name “*” is a shorthand for all role names defined in the deployment descriptor. "

and

"The special role name “**” is a shorthand for any authenticated user independent of role. When the special role name “**” appears in an authorization constraint, it indicates that any authenticated user, independent of role, is authorized to perform the constrained requests."

JACC 3.1.3.2 additionally says:

"When an auth-constraint names the reserved role-name, "*", all of the patterns in the containing security-constraint must be combined with all of the roles defined in the web application; which must not include the role “**” unless the application has defined an application role named “**”. Each WebResourcePermission object must be constructed using the qualified pattern as its name and with actions defined by combining (as defined in “Combining HTTP Methods”) the collections containing the pattern and occurring in a constraint that names (or implies via "*") the role to which the permission is being added."

JACC C.19.2 furthermore explicitly mentions that:

"the "*" role does not imply the "**" role unless the application has defined its own role named "**""

Furthermore, you can check the behaviour in the Java EE 8 RI GlassFish, which passes the JACC TCK:


There you see @PermitAll causes an unchecked permission to be created:


That is *exactly* what I want to do -- have a class level @RolesAllowed, with a @PermitAll on a few methods
which would mean "authenticated or unauthenticated, i don't care".
But I guess I'm still not convinced that the MP specs support this interpretation.

That's what PermitAll is indeed normally used for. 

As MP JWT is based on this somewhat implied security system, as mentioned, there's not a super strong guarantee that it supports it, unfortunately. The JAX-RS interpretation of @PermitAll is a combination of the EJB interpretation and the roles as they are, *implicitly*, defined by the Servlet container. This is because JAX-RS officially does not depend on Servlet, but in practice most if not all of the implementations do. This introduces another layer of uncertainty. Neither JAX-RS nor MP (re-)defines the role interpretation or resource constraints from Servlet, nor does it officially depend on Servlet, but it still (sort off) assumes Servlet security semantics are used anyway.

 You could say that in the spirit of the spec it *should* support it though.

Kind regards,
Arjan

Mark D. Anderson

unread,
Sep 30, 2019, 1:07:36 PM9/30/19
to microp...@googlegroups.com
Thanks Arjan.

I am reminded of the old poem Antigonish:
    Last night I saw upon the stair,
    A little man who wasn't there,
    He wasn't there again today
    Oh, how I wish he'd go away...
So i guess the little man would have an "unauthenticated role" :)

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

Arjan Tijms

unread,
Sep 30, 2019, 1:54:00 PM9/30/19
to Eclipse MicroProfile


On Monday, September 30, 2019 at 7:07:36 PM UTC+2, Mark D. Anderson wrote:
Thanks Arjan.

I am reminded of the old poem Antigonish:
    Last night I saw upon the stair,
    A little man who wasn't there,
    He wasn't there again today
    Oh, how I wish he'd go away...
So i guess the little man would have an "unauthenticated role" :)

Haha, if he's there, but hasn't identified himself, then indeed, he would have that role :P

 
To unsubscribe from this group and stop receiving emails from it, send an email to microp...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages