ServiceLoader usage in automatic module fails

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

ServiceLoader usage in automatic module fails

Christian Stein
Hi jigsaw team,

I discovered an issue with the ServiceLoader trying to load services on the
module-path, when the actual ServiceLoader.load() call resides in an
automatic module.

I compiled a small demo at [1] and it's console output is visible at [2].
If you want to re-run the demo, just call "jshell build.jsh" in the root
directory.

In summary, you have to elevate the automatic module to an explicit one,
via adding a module-info.class, to get the ServiceLoader load the service
on the module-path. This can be done with pro's [3] "modulefixer" plugin.

When resorting the class-path and provide a "META-INF/services" file and
also add the module to the class-path, I can get service loaded ... but
only within the unnamed module.

Is it an internal ServiceLoader bug or is this behaviour intented?

Might a theoretical "--add-uses <automatic-module-name>=<SPI>" help here?

Kind regards,
Christian

[1] https://github.com/sormuras/sawdust/tree/master/module-discoverer
[2] https://gist.github.com/sormuras/32ece436447ba5a3eac24e9db5842fb5
[3] https://github.com/forax/pro
Reply | Threaded
Open this post in threaded view
|

Re: ServiceLoader usage in automatic module fails

Alan Bateman


On 11/09/2017 11:03, Christian Stein wrote:

> Hi jigsaw team,
>
> I discovered an issue with the ServiceLoader trying to load services on the
> module-path, when the actual ServiceLoader.load() call resides in an
> automatic module.
>
> I compiled a small demo at [1] and it's console output is visible at [2].
> If you want to re-run the demo, just call "jshell build.jsh" in the root
> directory.
>
> In summary, you have to elevate the automatic module to an explicit one,
> via adding a module-info.class, to get the ServiceLoader load the service
> on the module-path. This can be done with pro's [3] "modulefixer" plugin.
>
> When resorting the class-path and provide a "META-INF/services" file and
> also add the module to the class-path, I can get service loaded ... but
> only within the unnamed module.
Which JAR file contains the service provider? You mentioned "restoring
the class-path and provide a META-INF/services". Does this mean you
removed the services configuration file when you had the JAR file on the
module path as an automatic module?

-Alan
Reply | Threaded
Open this post in threaded view
|

Re: ServiceLoader usage in automatic module fails

Christian Stein
> Which JAR file contains the service provider?

The service providing interface [1] is inside the api jar [2].
The service loader code resides in the Jupiter engine [3] jar and looks
like [4].

[1] org.junit.jupiter.api.extension.Extension
[2]
http://central.maven.org/maven2/org/junit/jupiter/junit-jupiter-api/5.0.0/
[3]
http://central.maven.org/maven2/org/junit/jupiter/junit-jupiter-engine/5.0.0/
[4]
https://github.com/junit-team/junit5/blob/master/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/ExtensionRegistry.java#L93


> You mentioned "restoring the class-path and provide a META-INF/services".
> Does this mean you removed the services configuration file when you
> had the JAR file on the module path as an automatic module?

No. The "demo" module is an explicit module with no service configuration.
It implements the SPI [1] and declares that in a module descriptor [5].

I wanted to write "resorting to the class-path". When I add a service
configuration file to the explicite demo module [6] at runtime and add
the location of the demo module to the class-path, the demo service
is loaded ... from the unnamed module.

[5]
https://github.com/sormuras/sawdust/blob/master/module-discoverer/demo/src/module-info.java
[6]
https://github.com/sormuras/sawdust/blob/master/module-discoverer/build.jsh#L82


On Mon, Sep 11, 2017 at 12:52 PM, Alan Bateman <[hidden email]>
wrote:

>
>
> On 11/09/2017 11:03, Christian Stein wrote:
>
>> Hi jigsaw team,
>>
>> I discovered an issue with the ServiceLoader trying to load services on
>> the
>> module-path, when the actual ServiceLoader.load() call resides in an
>> automatic module.
>>
>> I compiled a small demo at [1] and it's console output is visible at [2].
>> If you want to re-run the demo, just call "jshell build.jsh" in the root
>> directory.
>>
>> In summary, you have to elevate the automatic module to an explicit one,
>> via adding a module-info.class, to get the ServiceLoader load the service
>> on the module-path. This can be done with pro's [3] "modulefixer" plugin.
>>
>> When resorting the class-path and provide a "META-INF/services" file and
>> also add the module to the class-path, I can get service loaded ... but
>> only within the unnamed module.
>>
> Which JAR file contains the service provider? You mentioned "restoring the
> class-path and provide a META-INF/services". Does this mean you removed the
> services configuration file when you had the JAR file on the module path as
> an automatic module?
>
> -Alan
>
Reply | Threaded
Open this post in threaded view
|

Re: ServiceLoader usage in automatic module fails

Alan Bateman
In reply to this post by Alan Bateman


On 11/09/2017 11:52, Alan Bateman wrote:
> :
>
> Which JAR file contains the service provider? You mentioned "restoring
> the class-path and provide a META-INF/services". Does this mean you
> removed the services configuration file when you had the JAR file on
> the module path as an automatic module?
>
Also can you run with `--add-modules demo` as I assume the scenario you
is that "demo" is not resolved (because no modules `requires demo` and
no module declares that it uses the service type that demo provides).

-Alan
Reply | Threaded
Open this post in threaded view
|

Re: ServiceLoader usage in automatic module fails

Christian Stein
On Mon, Sep 11, 2017 at 1:17 PM, Alan Bateman <[hidden email]>
wrote:

[...]
>
> Also can you run with `--add-modules demo` as I assume the scenario you is
> that "demo" is not resolved (because no modules `requires demo` and no
> module declares that it uses the service type that demo provides).
>
> -Alan
>

Thanks, Alan. That worked like charm!
Reply | Threaded
Open this post in threaded view
|

Re: ServiceLoader usage in automatic module fails

Alan Bateman


On 11/09/2017 12:26, Christian Stein wrote:

> On Mon, Sep 11, 2017 at 1:17 PM, Alan Bateman <[hidden email]>
> wrote:
>
> [...]
>> Also can you run with `--add-modules demo` as I assume the scenario you is
>> that "demo" is not resolved (because no modules `requires demo` and no
>> module declares that it uses the service type that demo provides).
>>
>> -Alan
>>
> Thanks, Alan. That worked like charm!
You can also use `--show-module-resolution` to get traces at startup and
satisfied yourself that it working correctly.

-Alan
Reply | Threaded
Open this post in threaded view
|

Re: ServiceLoader usage in automatic module fails

Christian Stein
On Mon, Sep 11, 2017 at 2:21 PM, Alan Bateman <[hidden email]>
 wrote:

> [...]
>
> You can also use `--show-module-resolution` to get traces at startup and
> satisfied yourself that it working correctly.


Using the symbolic constant `--add-modules ALL-MODULE-PATH` works even
better when scanning module contents for test classes.

See [1] for a proof-of-concept implementation that ship with JUnit 5.1...

Cheers,
Christian

[1] https://github.com/junit-team/junit5/pull/1057#issuecomment-328806352