Ad 1 (provider implementations cannot be code generated without major problems)
I understand that annotation processing should not mutate elements, and I never 
suggested it should be done. I am looking for a solution provided by the 
language (whatever that may be).

I am not sure if you are aware of the complexity of the proposed "It's on the 
framework to post-process
module-info.class so it has `provides` clauses"

Considering that we currently have multiple build frameworks, and for each of 
those the postprocessing must be done differently, we are also opening the 
possibility of the user not configuring the postprocessing to happen at all. 
Just the first part (Maven plugins, Gradle plugins, possible other systems) is 
a major maintenance issue.
In addition, the compiled code deployed with the application differs from its 
source code, making troubleshooting more complicated.

I understand it is easy to dismiss these problems and let us (as framework 
owners) handle it. You are in the end forcing us to do it differently for each 
framework - which in the end is a problem for our users.

The result that other frameworks reached (and I was trying not to do), and we 
will switch to as well, is to design our own extensibility approach that is 
based on resources rather than on module-info.java. This makes it once again 
harder for users, as they cannot use the tools the language provides.

Pushing us to post-processing the bytecode: if there was an event in the 
compiler with extensibility similar to annotation processors (i.e. 
ClassPostProcessor) using the ClassFile API, I can imagine this being done, as 
it is still part of a single compilation run (but as far as I know, there is no 
such possibility).

Ad 2 (requires static on provider module)
As far as I have seen the analysis of current Maven repository, Helidon is the 
only bigger framework that has embraced modularization.
So "a large number of users" will not find the current rules unworkable, as 
there is not "a large number of users" using JPMS.
As one of the users of it on a larger scale, I can tell you this is a major 
restriction for using JPMS together with ServiceLoader (and as mentioned above, 
we will stop using ServiceLoader because of this).

Ad 3 (public provider)
I understand this is not a critical feature

Ad 4 (duality between module path and classpath)
You have mentioned "It's relatively low risk, but also low reward, so we aren't 
going to investigate it further."
Once again I am not sure whose "low reward" you have in mind. I understand that 
in the language and for language developers this may not mean much. But for the 
users, frameworks etc. this is quite a big thing - we are now required to do 
another post-processing of our libraries to ensure we have both (module-info 
provides and META-INF/services).
The reward is that new libraries can work both on classpath and on module path. 
And considering how many people use JPMS, this is quite a critical behavior for 
anything we create.

Tomas

________________________________
Od: jigsaw-dev <jigsaw-dev-r...@openjdk.org> za uživatele Alex Buckley 
<alex.buck...@oracle.com>
Odesláno: úterý 30. ledna 2024 20:05
Komu: jigsaw-dev <jigsaw-...@openjdk.java.net>
Předmět: Re: Java extensibility and JPMS (ServiceLoader)

On 1/19/2024 5:02 AM, Tomas Langer wrote:
> Helidon currently has around 300 modules with module-info.java. In
> general, this has improved our module structure and design.
> Yet, we are now encountering some major issues related to extensibility.
>   I will put down a few points that are problematic, and explain each in
> detail further in the e-mail (it is quite long, sorry about that).
>
> 1. provider implementations cannot be code generated without major problems

Annotation processing is designed to avoid mutating the elements, so it
would be a fundamental change to allow mutation of module elements in
the annotation processing API. It's on the framework to post-process
module-info.class so it has `provides` clauses. The framework can use
the ClassFile API to do this.

It's not "weird" for a framework to modify module-info.class to ensure
that code in the module has the right execution environment. Another
example would be a tool that injects calls to a logging API into user
code, then has to post-process module-info.class to add `requires
logging.lib;`.

> 2. the provider interface module MUST be on module path, even if it
> could have `requires static`

Relaxing module resolution to allow a module to `provides` an interface
that it can't access is do-able, but the implications are unknown. It
would be unfortunate if resolution succeeded but then unforeseen
exceptions occur when faraway code tries to access the missing
interface. We'll leave JDK-8299504 open for now, but we would need
evidence that a large number of users are finding the current rules
unworkable before actively looking at `provides` again.

> 3. the provider implementation must be public with public constructor
> 4. duality of definition between module path and class path

These requests for ServiceLoader to (i) support package-private
providers and (ii) inspect module-info.class files for `provides`
clauses in JARs on the classpath both stem from insisting that modular
JARs can be deployed on the classpath without losing functionality. This
is a net-new requirement on the module system. It's relatively low risk,
but also low reward, so we aren't going to investigate it further.

Alex

Reply via email to