I'm currently running into an issue that behaves unexpected as far as I can 
see. Let's say there are two service types, A and B. The module `main` in the 
boot layer has a uses constraint on A. Module `main` instantiates a new 
ModuleLayer with the following code:

      ModuleFinder finder = ModuleFinder.of(dir.toPath());

      ModuleLayer parent = ModuleLayer.boot();
      Configuration cf = parent.configuration()
        .resolveAndBind(finder, ModuleFinder.of(), Set.of());

      ClassLoader scl = ClassLoader.getSystemClassLoader();
      ModuleLayer layer = parent.defineModulesWithOneLoader(cf, scl);

      // Now use new A providers from the layer:
      ServiceLoader.load(layer, A.class).forEach(...)

When `dir` contains a single provider module that provides an implementation of 
A, this works fine. What doesn't work, is if I have a directory with a provider 
module providing an A implementation, where this A implementation in turn has a 
uses constraint on B. When I check `layer.modules()`, I can see that the B 
provider modules do get resolved into the layer (they're also in `dir`). 
However, `ServiceLoader.load(B.class)`, which is part of the A service 
implementation code, returns no instances. How can I make sure the B service 
providers are bound as well within the layer?

To answer my own question, after some thinking and experimentation I found out 
that the A implementation should use the following code:

     ServiceLoader.load(getClass().getModule().getLayer(), B.class)

So... should I start writing all my ServiceLoader calls this way from now on, 
if I want to make sure my modules work regardless of whether they're loaded in 
the boot layer or another layer? Wouldn't it be more logical for ServiceLoader 
to always work from the current layer (hm, that would probably break the 
current classloader based contract)? Am I missing another option?


Sander



Reply via email to