<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">
<div class="">An optional service is something that could be considered, but I think there’s a difference in expectations that underlies this entire discussion.</div>
<div class=""><br class="">
</div>
<div class="">Java’s classpath offers a very dynamic model of program configurations where class resolution is *expected* to possibly fail at runtime. This has some disadvantages but also some clear advantages. Modules are not meant to continue the same model
 by other means, but to offer a very different one, with its own pros and cons. Dialing back Java’s dynamism is their point, and in more ways than one (both strong encapsulation and reliable configuration are about restricting dynamism in favour of more static
 guarantees).</div>
<div class=""><br class="">
</div>
<div class="">When you configure the application on the command line you already know whether or not you wish to include a module that contains the service interface in the configuration. If you don’t, then don’t include modules that provide that service. There
 is no need to “work around” the lesser dynamism. That is a different experience from the classpath’s model of “I’ll throw some stuff in there, maybe it’s needed maybe it’s not; maybe it’s consistent, maybe not,” but it is different by design.</div>
<div class=""><br class="">
</div>
<div class="">In particular, `requires static` — intended for compile-time dependencies — also doesn’t work like the classpath. If you happen to reference a class that exists on the class path it will be resolved, but `requires static` is insufficient to resolve
 the module. Which makes me wonder, what is the root of the optionality in your code? I.e. how does io.avaje.inject come to be resolved?</div>
<div class=""><br class="">
</div>
<div class="">— Ron</div>
<div><br class="">
<blockquote type="cite" class="">
<div class="">On 18 Apr 2023, at 11:50, Rob Bygrave <<a href="mailto:robin.bygrave@gmail.com" class="">robin.bygrave@gmail.com</a>> wrote:</div>
<br class="Apple-interchange-newline">
<div class="">
<div dir="ltr" class="">
<div class="">
<div class=""><i class="">> `requires static` is more for use-cases like annotations that do not need to be present at run-time</i></div>
<div class=""><br class="">
</div>
<div class="">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 class=""><br class="">
</div>
<i class="">
<div class=""><i class=""><br class="">
</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 class=""><br class="">
</div>
<div class="">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 class=""><br class="">
</div>
<div class="">Of those 25 requires static, 5 of those are dependencies on optional annotations and 20 are optional dependencies that are
<i class="">NOT</i> annotations. They all match to maven optional true dependencies (self fulfilling I know).</div>
<div class=""><br class="">
</div>
<div class="">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 class=""><br class="">
</div>
<div class=""><br class="">
</div>
<div class="">> <i class="">do not need to be present at run-time.</i></div>
<div class=""><i class=""><br class="">
</i></div>
<div class="">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 class=""><br class="">
</div>
<div class="">*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 class="">provides p.S</i> to be optional). </div>
<div class=""><br class="">
</div>
<div class=""><br class="">
</div>
<div class="">> <i class="">It could of course be extended </i></div>
<div class=""><i class=""><br class="">
</i></div>
<div class="">Extended? What is wrong with how requires static works now? How are you suggesting it could be extended and for what purpose?</div>
<div class=""><br class="">
</div>
<div class=""><br class="">
</div>
<div class="">> <i class="">but it's a slippery slope that ultimately amounts to giving up on reliability.</i></div>
<div class=""><i class=""><br class="">
</i></div>
<div class="">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 class=""><br class="">
</div>
<div class=""><br class="">
</div>
<div class="">Thanks, Rob.</div>
</div>
<br class="">
<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" class="">Alan.Bateman@oracle.com</a>> wrote:<br class="">
</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 class=""><br class="">
On 17/04/2023 15:20, Rob Bygrave wrote:<br class="">
<blockquote type="cite" class="">
<div dir="ltr" class=""><i class="">:</i>
<div class=""><span class=""><br class="">
</span></div>
<div class=""><span class=""><br class="">
</span></div>
<div class=""><span class="">> </span><i class=""><span class="">is it reasonable to consider that ServiceLoader is the *only* vector by which the implementation class will be instantiated?<span class=""> </span></span></i></div>
<div class=""><span class=""><br class="">
</span></div>
<div class=""><span class="">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 class="">the use of requires static for this case is explicit and intentional</i>.  </span></div>
<div class=""><span class=""><br class="">
</span></div>
<div class=""><span class="">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 class="">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 class="">
</div>
</blockquote>
<br class="">
In your example, module io.avaje.config declares that it provides an implementation of
<span style="font-variant-ligatures:no-common-ligatures" class="">io.avaje.inject.spi.PropertyRequiresPlugin. There is nothing to connect this to
</span><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">`requires static
</span><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">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" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">io.avaje.inject
 to see if exports </span></span></span></span></span></span><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">io.avaje.inject.spi
</span></span></span></span></span></span></span><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">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" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">`requires
 static </span><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">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" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""></span><span style="font-variant-ligatures:no-common-ligatures" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">io.avaje.inject
</span></span></span></span></span></span></span></span></span></span></span></span></span>exports packages with service types.<br class="">
<br class="">
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 class="">
<br class="">
-Alan<br class="">
</div>
</blockquote>
</div>
</div>
</blockquote>
</div>
<br class="">
</body>
</html>