<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    On 11/12/2024 19:31, David Lloyd wrote:<br>
    <blockquote type="cite" cite="mid:CANghgrRDcJieY7XhibMnxpH2GXT7+zdy8iv7zCf6RKSAkTsgjA@mail.gmail.com">
      
      <div dir="ltr">
        <div>
          <div class="gmail_default" style="font-family:arial,helvetica,sans-serif">I'm once
            again experimenting with modularizing some of our runtime
            projects (Quarkus, WildFly) using JDK modules. Among the
            various problems I've encountered, this one is one I haven't
            cracked yet and seems like an oversight.</div>
          <div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br>
          </div>
          <div class="gmail_default" style="font-family:arial,helvetica,sans-serif">I am
            currently experimenting with a one-module-per-layer design
            which allows us certain capabilities (like lazy loading of
            modules, late binding of dependencies, and circularity in
            dependencies), and also allows us to create module graphs
            that can mix in "unnamed" modules for libraries which don't
            yet work properly as named modules, as well as automatic
            modules for libraries which can work as modules but don't
            yet define a descriptor.</div>
          <div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br>
          </div>
          <div class="gmail_default" style="font-family:arial,helvetica,sans-serif">However I
            have discovered an important difference between service
            loaders which load services by class loader (for example,
            those found in Microprofile and Jakarta frameworks) and
            those which load by module layer (none?) which is preventing
            things from working properly.</div>
          <div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br>
          </div>
          <div class="gmail_default" style="font-family:arial,helvetica,sans-serif">When I load a
            service by layer, after searching the given layer, the
            parent layers of that layer are then searched in order,
            recursing up the graph. (Sometimes the same service could be
            returned multiple times when there are diamonds in the layer
            graph, but that's a different problem.)</div>
          <div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br>
          </div>
          <div class="gmail_default" style="font-family:arial,helvetica,sans-serif">When I load a
            service by class loader, if the service is not found in the
            class loader's defined layers, then the search terminates
            and the service is considered not found, even if the service
            provider exists in a parent layer of one of those layers.
            This essentially means that all frameworks which are loading
            services by class loader (and using the class loader of the
            framework itself is typical here) will also need all of
            their implementations to coexist in one of the layers
            defined by that class loader - or else they must be defined
            in the unnamed module (in which case it will always be
            found).</div>
          <div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br>
          </div>
          <div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Ironically,
            it *will* search the parent class loading delegation chain
            for layers which contain service implementations. The point
            of using module layers though is that they can have multiple
            parents, departing from this single-delegation model. In our
            class-loader-per-module setup, we do not use the parent
            class loader delegation as it would be meaningless in that
            context.</div>
          <div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br>
          </div>
          <div class="gmail_default" style="font-family:arial,helvetica,sans-serif">A good
            solution would be to modify service loading by class loader
            to also search parent layers of each layer defined to that
            class loader. This seems like it would be fairly easy to
            implement, but might possibly have subtle compatibility
            implications for very specific environments which have a
            module-per-class-loader situation along with multiple
            layers.</div>
          <br>
        </div>
      </div>
    </blockquote>
    If ServiceLoader.load is invoked with a ClassLoader then it lazily
    iterates through the class loader delegation chain. If
    ServiceLoader.load is invoked with a ModuleLayer then it iterates
    through the module layers.  The former has deliberately limited
    support for cases where a class loader is used by a module layer but
    doing what you propose is adding more complexity for what seems like
    a really niche usage. I would worry that changing it along the lines
    you propose would result in something that only a few people could
    understand.<br>
    <br>
    Have you looked at changing these frameworks to work with modules
    and specify a module layer to ServiceLoader.load?<br>
    <br>
    -Alan<br>
  </body>
</html>