Using ServiceLoader with modules

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Using ServiceLoader with modules

Alex Buckley
I came across a recent blog entry about using ServiceLoader in a modular
environment:

   https://blog.frankel.ch/migrating-serviceloader-java-9-module-system/

Unfortunately, it is completely wrong in its advice on "Migrating to the
Java Platform Module System". I have seen the same bad advice on
StackOverflow, so let me correct it here, as simply as possible:

1. The module containing the implementation SHOULD NOT export the
implementation package.

2. The module containing the client MUST say that it uses the service
interface.

See the "Deploying service providers as modules" section of
https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/util/ServiceLoader.html

The whole point of integrating ServiceLoader with the module system was
get the configuration documented explicitly, via `uses` and `provides`
clauses. Benefits: the implementation is strongly encapsulated (no
`exports`), and the client's service lookup is speedy because its
dependency (`uses`) was found cheaply during startup. Eventually, as the
blog rightly says, "only the configuration changes: the Service Loader
code itself in the client doesn’t change."

Alex
Reply | Threaded
Open this post in threaded view
|

Re: Using ServiceLoader with modules

Alex Buckley
// cc'ing the list because best practices should be public, and
// because it's easier to refer people to it in five years time

Hi Christian,

On 10/14/2019 12:16 PM, Christian Stein wrote:
>   just read your mail and was wondering if this extrapolation is correct:
>
>     A module that does not export any package should never need to
>     declare a "requires" as transitive.

Some qualification needed, I think. There are (at least) two kinds of
"top level" module that commonly have no `exports` clauses:

1. An "application module" intended to be launched (`java -m bizapp`)
rather than programmed against. I agree that this kind of module should
not use `requires transitive`.

2. An "aggregator module" intended to present a facade composed from the
APIs of other modules. For example, the `java.se` module has no
`exports`, but makes good use of `requires transitive`. (See
http://hg.openjdk.java.net/jdk/jdk/file/tip/src/java.se/share/classes/module-info.java.)

> For example, I should remove all `transitive` modifiers from this module
>
> module org.junit.platform.console {
>    requires transitive org.apiguardian.api;
>    requires transitive org.junit.platform.reporting;
>    provides java.util.spi.ToolProvider
>        with org.junit.platform.console.ConsoleLauncherToolProvider;
> }

This "console" module certainly looks like #1 rather than #2.

Alex