Tomas,

I realize that you want to allow your modular JARs to be deployed on the classpath and still enjoy some degree of encapsulation.

However, mapping packages 1:1 to modules isn't the right way to use the module system. You get to formalize the system structure, and will be forced to break any legacy cycles between packages, but every module will export 100% of its packages, so there's no real information hiding. The maintainer of a module in one subsystem can freely require a module in another subsystem and access the exported-but-not-really-supported package of that other subsystem, so over time, a ball of mud will re-emerge.

Having "internal" packages is a _feature_ of modules, not a problem. It's only a problem if those modules are deployed on the classpath, and we don't recommend doing that.

On point 3: The requirement that a provider class must be public with a public ctor comes from the original design of ServiceLoader. This resulted in providers that were "too public", so we used the module system to solve that problem: you can take existing providers, "hide" them in unexported/internal packages of modules, and service consumers are not impacted at all.

Except for the small addition of "provider methods" as an alternative to public ctors, we took ServiceLoader in Java 9 as we found it. Evolving ServiceLoader in Java 23+ to allow providers with very limited accessibility -- package-access classes / ctors / provider methods -- is not incompatible with anything in the module system. In fact, keeping the circle of code that can instantiate providers as tight as possible is a good thing. However, we haven't heard the request for package-access providers from many people, and working on that feature would mean not working on something else, so it's unlikely that the feature will appear in the foreseeable future.

Alex

On 1/22/2024 3:30 PM, Tomas Langer wrote:
We have a single module/single package approach, so all internal classes are hidden by visibility (package local) and not by package (as that cannot be enforced on classpath. Using more than one package usually results in internal packages and in requirement to have some methods public, so classes in other packages of your module can access them (where we can live with package local only...)

Tomas

Zasláno z Outlooku pro Android <https://aka.ms/AAb9ysg>
------------------------------------------------------------------------
*From:* jigsaw-dev <jigsaw-dev-r...@openjdk.org> on behalf of Alex Buckley <alex.buck...@oracle.com>
*Sent:* Monday, January 22, 2024 9:13:39 PM
*To:* jigsaw-dev@openjdk.org <jigsaw-dev@openjdk.org>
*Subject:* Re: Java extensibility and JPMS (ServiceLoader)
Tomas,

A clarification for point 3:

On 1/19/2024 5:02 AM, Tomas Langer wrote:
*Ad 3 - Provider implementation must be public with public constructor*
-------------------------------------
Details:
Provider implementations are not supposed to be visible to users - they are not public API of my module (the fact that I provide a service is part of my public API). Right now there is only one option to work around this, and it only works in JPMS, and in my opinion it brings in even more problems - put the provider implementation in an un-exported package. The problem with this approach is that now the provider implementation MUST use only public methods of my module, thus creating even more public APIs, where if I just put it in my exported package, I can use package private methods of my other classes to implement the service (so I pay the price of having one public class with one public constructor agains multiple public classes and public methods). Also the "hiding" in unexported package is lost when on classpath anyway...

I don't understand what you mean by "the provider implementation MUST
use only public methods of my module". You have an arrangement of
modules and packages in mind that I simply cannot see -- please share it.

Alex

Reply via email to