<div dir="ltr"><i>> <span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures">In this case, it amounts to giving up on a post resolution check and allowing all service providers to have a dangling reference to a service type.</span></span></span></span></span></span></span><br></i><div><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><br></span></span></span></span></span></span></span></div><div><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures">Noting that the effect of this is also that use of ServiceLoader works differently in module-path compared to classpath for this case. Use of </span></span></span></span></span></span></span>ServiceLoader wrt optional service loading that works in classpath will not work in module-path (resolution error).</div><div><br></div><div>I come back to Alex's comment in the bug report:</div><div><br></div><div><i>> Alex: <span style="color:rgb(23,43,77);font-family:"DejaVu Sans",sans-serif;font-size:14px">All of this boils down to: if the implementation module says `provides`, then is it reasonable to consider that ServiceLoader is the *only* vector by which the implementation class will be instantiated? If yes, then module resolution should perhaps be tolerant of a `provides` that specifies a missing service interface.</span><span class="gmail-Apple-converted-space" style="color:rgb(23,43,77);font-family:"DejaVu Sans",sans-serif;font-size:14px"> </span></i></div><div><br></div>Obviously I'm in the <i>"module resolution should be tolerant of a `provides` that specifies a missing service interface. "</i> camp. I'd happily trade the runtime resolution error (that fails fast) for the "consistent with classpath" only error if something else tries to instantiate the service (and p.S isn't in module-path).<div><br><div>The workarounds at this point look like:</div><div>- Don't use module-path, just stick to classpath</div><div>- Re-design, likely extracting out the service interface into its own artifact and make it a hard dependency of the module implementing the service</div><div>- Don't use ServiceLoader</div><div><br></div><div><br></div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, 18 Apr 2023 at 22:50, <<a href="mailto:jigsaw-dev-request@openjdk.org">jigsaw-dev-request@openjdk.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">Send jigsaw-dev mailing list submissions to<br>
        <a href="mailto:jigsaw-dev@openjdk.org" target="_blank">jigsaw-dev@openjdk.org</a><br>
<br>
To subscribe or unsubscribe via the World Wide Web, visit<br>
        <a href="https://mail.openjdk.org/mailman/listinfo/jigsaw-dev" rel="noreferrer" target="_blank">https://mail.openjdk.org/mailman/listinfo/jigsaw-dev</a><br>
or, via email, send a message with subject or body 'help' to<br>
        <a href="mailto:jigsaw-dev-request@openjdk.org" target="_blank">jigsaw-dev-request@openjdk.org</a><br>
<br>
You can reach the person managing the list at<br>
        <a href="mailto:jigsaw-dev-owner@openjdk.org" target="_blank">jigsaw-dev-owner@openjdk.org</a><br>
<br>
When replying, please edit your Subject line so it is more specific<br>
than "Re: Contents of jigsaw-dev digest..."<br>
Today's Topics:<br>
<br>
   1. Re: provides and requires static ... runtime error (Alan Bateman)<br>
   2. Re: provides and requires static ... runtime error (Rob Bygrave)<br>
<br><br><br>---------- Forwarded message ----------<br>From: Alan Bateman <<a href="mailto:Alan.Bateman@oracle.com" target="_blank">Alan.Bateman@oracle.com</a>><br>To: Rob Bygrave <<a href="mailto:robin.bygrave@gmail.com" target="_blank">robin.bygrave@gmail.com</a>><br>Cc: <a href="mailto:jigsaw-dev@openjdk.java.net" target="_blank">jigsaw-dev@openjdk.java.net</a><br>Bcc: <br>Date: Tue, 18 Apr 2023 09:05:06 +0100<br>Subject: Re: provides and requires static ... runtime error<br>

  
  <div>
    <br>
    On 17/04/2023 15:20, Rob Bygrave wrote:<br>
    <blockquote type="cite">
      
      <div dir="ltr"><i>:</i>
        <div><span><br>
          </span></div>
        <div><span><br>
          </span></div>
        <div><span>> </span><i><span>is it reasonable to
              consider that ServiceLoader is the *only* vector by which
              the implementation class will be instantiated?<span> </span></span></i></div>
        <div><span><br>
          </span></div>
        <div><span>In my view this is
            expected and imo I get there by thinking in the opposite
            direction from the provides p.S type to the requires static
            rather than the other way around. That is, the p.S type is
            only available via requires static hence it is expected to
            potentially not exist at runtime in the module-path. That
            is, if p.S was expected to exist at runtime it would be
            "read" via a requires or requires transient clause and not
            via a requires static - <i>the use of requires static for
              this case is explicit and intentional</i>.  </span></div>
        <div><span><br>
          </span></div>
        <div><span>In using requires
            static ... imo we are explicitly going out-of-our-way to say
            "the types here might not be available at runtime" and the
            classic case for this as I see it is this case of providing
            an optional service, that will only be service loaded if the
            user of that service is in the classpath / module-path. <i>IF</i>
            the module that is the user of a service is in the classpath
            / module-path then that module will ensure that the p.S type
            is in the module-path.</span></div>
        <br>
      </div>
    </blockquote>
    <br>
    In your example, module io.avaje.config declares that it provides an
    implementation of <span style="font-variant-ligatures:no-common-ligatures">io.avaje.inject.spi.PropertyRequiresPlugin.
      There is nothing to connect this to </span><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures">`requires
        static </span><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures">io.avaje.inject`.
          The module system would need to search "far and wide" for </span></span></span><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures">io.avaje.inject
                to see if exports </span></span></span></span></span></span><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures">io.avaje.inject.spi
                </span></span></span></span></span></span></span><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures">to
                  io.avaje.config, otherwise there is no way for it to
                  know that the "missing package" is in a module that is
                  not required to be present at run-time. In other
                  words, </span></span></span></span></span></span></span><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures">`requires
                      static </span><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures">io.avaje.inject` does
                        not convey to the module system that </span></span></span></span></span></span></span></span></span></span><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures">
                                        </span><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures">io.avaje.inject </span></span></span></span></span></span></span></span></span></span></span></span></span>exports
                  packages with service types.<br>
                  <br>
                  I understand there is a temptation to compare
                  `requires static` with optional dependences in Maven
                  but they are not the same thing. `requires static` is
                  more for use-cases like annotations that do not need
                  to be present at run-time. It could of course be
                  extended but it's a slippery slope that ultimately
                  amounts to giving up on reliability. In this case, it
                  amounts to giving up on a post resolution check and
                  allowing all service providers to have a dangling
                  reference to a service type.</span></span></span></span></span></span></span><br>
    <br>
    -Alan<br>
  </div>

<br><br><br>---------- Forwarded message ----------<br>From: Rob Bygrave <<a href="mailto:robin.bygrave@gmail.com" target="_blank">robin.bygrave@gmail.com</a>><br>To: Alan Bateman <<a href="mailto:Alan.Bateman@oracle.com" target="_blank">Alan.Bateman@oracle.com</a>><br>Cc: <a href="mailto:jigsaw-dev@openjdk.java.net" target="_blank">jigsaw-dev@openjdk.java.net</a><br>Bcc: <br>Date: Tue, 18 Apr 2023 22:50:30 +1200<br>Subject: Re: provides and requires static ... runtime error<br><div dir="ltr"><div><div><i>> `requires static` is more for use-cases like annotations that do not need to be present at run-time</i></div><div><br></div><div>I am aware that annotations have a retention policy but otherwise why are we specifically saying "like annotations" here as opposed to just saying "types"? </div></div><div><br></div><i><div><i><br></i></div>> I understand there is a temptation to compare `requires static` with optional dependences in Maven but they are not the same thing. `requires static` is more for use-cases like annotations that do not need to be present at run-time. It could of course be extended but it's a slippery slope that ultimately amounts to giving up on reliability.</i><div><br></div><div>Background:  I also maintain Ebean ORM which is made up of 20+ modules (+ 3rd party dependencies) and works with classpath and module-path. A quick search for "requires static" there shows me 25 uses of requires static (192 requires clauses in total on the core modules, I'm suggesting this is a non-trivial use of module-path that uses a decent amount of requires static).  </div><div><br></div><div>Of those 25 requires static, 5 of those are dependencies on optional annotations and 20 are optional dependencies that are <i>NOT</i> annotations. They all match to maven optional true dependencies (self fulfilling I know).</div><div><br></div><div>For all these cases requires static has worked exactly as I expect and exactly the same with classpath and module-path. There have been no issues.  No issues when the requires static was for annotations and no issues when the requires static was for normal types (not annotations). </div><div><br></div><div><br></div><div>> <i>do not need to be present at run-time.</i></div><div><i><br></i></div><div>So for ebean orm, it is using [requires static / optional at runtime] types that are both annotations and normal class types and they are all potentially not present at run-time. There is a suggestion there is a slippery slope for the requires static types that are not annotations? I'm wondering why? As in, optional dependencies have been reasonably extensively used and there has been no issue hit here with module-path and requires static and everything has worked as expected*. </div><div><br></div><div>*Except the issue noted in this thread which imo isn't an issue with requires static. That is, I'm now aware of the issue with ServiceLoader in module-path not working when provides p.S is via requires static (unlike classpath) ... but in my mind that issue isn't really an issue with requires static per say but instead it is an issue with the runtime module resolution (by not allowing <i>provides p.S</i> to be optional). </div><div><br></div><div><br></div><div>> <i>It could of course be extended </i></div><div><i><br></i></div><div>Extended? What is wrong with how requires static works now? How are you suggesting it could be extended and for what purpose?</div><div><br></div><div><br></div><div>> <i>but it's a slippery slope that ultimately amounts to giving up on reliability.</i></div><div><i><br></i></div><div>Well, optional dependencies by their nature are sometimes dynamically determined at runtime which isn't ideal but also not difficult or new. Can you give an example of what you mean by this?</div><div><br></div><div><br></div><div>Thanks, Rob.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, 18 Apr 2023 at 20:05, Alan Bateman <<a href="mailto:Alan.Bateman@oracle.com" target="_blank">Alan.Bateman@oracle.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">

  
  <div>
    <br>
    On 17/04/2023 15:20, Rob Bygrave wrote:<br>
    <blockquote type="cite">
      
      <div dir="ltr"><i>:</i>
        <div><span><br>
          </span></div>
        <div><span><br>
          </span></div>
        <div><span>> </span><i><span>is it reasonable to
              consider that ServiceLoader is the *only* vector by which
              the implementation class will be instantiated?<span> </span></span></i></div>
        <div><span><br>
          </span></div>
        <div><span>In my view this is
            expected and imo I get there by thinking in the opposite
            direction from the provides p.S type to the requires static
            rather than the other way around. That is, the p.S type is
            only available via requires static hence it is expected to
            potentially not exist at runtime in the module-path. That
            is, if p.S was expected to exist at runtime it would be
            "read" via a requires or requires transient clause and not
            via a requires static - <i>the use of requires static for
              this case is explicit and intentional</i>.  </span></div>
        <div><span><br>
          </span></div>
        <div><span>In using requires
            static ... imo we are explicitly going out-of-our-way to say
            "the types here might not be available at runtime" and the
            classic case for this as I see it is this case of providing
            an optional service, that will only be service loaded if the
            user of that service is in the classpath / module-path. <i>IF</i>
            the module that is the user of a service is in the classpath
            / module-path then that module will ensure that the p.S type
            is in the module-path.</span></div>
        <br>
      </div>
    </blockquote>
    <br>
    In your example, module io.avaje.config declares that it provides an
    implementation of <span style="font-variant-ligatures:no-common-ligatures">io.avaje.inject.spi.PropertyRequiresPlugin.
      There is nothing to connect this to </span><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures">`requires
        static </span><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures">io.avaje.inject`.
          The module system would need to search "far and wide" for </span></span></span><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures">io.avaje.inject
                to see if exports </span></span></span></span></span></span><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures">io.avaje.inject.spi
                </span></span></span></span></span></span></span><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures">to
                  io.avaje.config, otherwise there is no way for it to
                  know that the "missing package" is in a module that is
                  not required to be present at run-time. In other
                  words, </span></span></span></span></span></span></span><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures">`requires
                      static </span><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures">io.avaje.inject` does
                        not convey to the module system that </span></span></span></span></span></span></span></span></span></span><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures">
                                        </span><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures">io.avaje.inject </span></span></span></span></span></span></span></span></span></span></span></span></span>exports
                  packages with service types.<br>
                  <br>
                  I understand there is a temptation to compare
                  `requires static` with optional dependences in Maven
                  but they are not the same thing. `requires static` is
                  more for use-cases like annotations that do not need
                  to be present at run-time. It could of course be
                  extended but it's a slippery slope that ultimately
                  amounts to giving up on reliability. In this case, it
                  amounts to giving up on a post resolution check and
                  allowing all service providers to have a dangling
                  reference to a service type.</span></span></span></span></span></span></span><br>
    <br>
    -Alan<br>
  </div>

</blockquote></div>
</blockquote></div>