*> 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.*
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 ServiceLoader wrt optional service loading that works in classpath will not work in module-path (resolution error). I come back to Alex's comment in the bug report: *> Alex: 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. * Obviously I'm in the *"module resolution should be tolerant of a `provides` that specifies a missing service interface. "* 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). The workarounds at this point look like: - Don't use module-path, just stick to classpath - Re-design, likely extracting out the service interface into its own artifact and make it a hard dependency of the module implementing the service - Don't use ServiceLoader On Tue, 18 Apr 2023 at 22:50, <jigsaw-dev-requ...@openjdk.org> wrote: > Send jigsaw-dev mailing list submissions to > jigsaw-dev@openjdk.org > > To subscribe or unsubscribe via the World Wide Web, visit > https://mail.openjdk.org/mailman/listinfo/jigsaw-dev > or, via email, send a message with subject or body 'help' to > jigsaw-dev-requ...@openjdk.org > > You can reach the person managing the list at > jigsaw-dev-ow...@openjdk.org > > When replying, please edit your Subject line so it is more specific > than "Re: Contents of jigsaw-dev digest..." > Today's Topics: > > 1. Re: provides and requires static ... runtime error (Alan Bateman) > 2. Re: provides and requires static ... runtime error (Rob Bygrave) > > > > ---------- Forwarded message ---------- > From: Alan Bateman <alan.bate...@oracle.com> > To: Rob Bygrave <robin.bygr...@gmail.com> > Cc: jigsaw-...@openjdk.java.net > Bcc: > Date: Tue, 18 Apr 2023 09:05:06 +0100 > Subject: Re: provides and requires static ... runtime error > > On 17/04/2023 15:20, Rob Bygrave wrote: > > *:* > > > > *is it reasonable to consider that ServiceLoader is the *only* vector > by which the implementation class will be instantiated? * > > 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 - *the use of requires static for this case is explicit > and intentional*. > > 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. *IF* 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. > > > In your example, module io.avaje.config declares that it provides an > implementation of io.avaje.inject.spi.PropertyRequiresPlugin. There is > nothing to connect this to `requires static io.avaje.inject`. The module > system would need to search "far and wide" for io.avaje.inject to see if > exports io.avaje.inject.spi 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, `requires static > io.avaje.inject` > does not convey to the module system that io.avaje.inject exports > packages with service types. > > 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. > > -Alan > > > > ---------- Forwarded message ---------- > From: Rob Bygrave <robin.bygr...@gmail.com> > To: Alan Bateman <alan.bate...@oracle.com> > Cc: jigsaw-...@openjdk.java.net > Bcc: > Date: Tue, 18 Apr 2023 22:50:30 +1200 > Subject: Re: provides and requires static ... runtime error > *> `requires static` is more for use-cases like annotations that do not > need to be present at run-time* > > 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"? > > > *> 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.* > > 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). > > Of those 25 requires static, 5 of those are dependencies on optional > annotations and 20 are optional dependencies that are *NOT* annotations. > They all match to maven optional true dependencies (self fulfilling I know). > > 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). > > > > *do not need to be present at run-time.* > > 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*. > > *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 *provides p.S* to be optional). > > > > *It could of course be extended * > > Extended? What is wrong with how requires static works now? How > are you suggesting it could be extended and for what purpose? > > > > *but it's a slippery slope that ultimately amounts to giving up on > reliability.* > > 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? > > > Thanks, Rob. > > On Tue, 18 Apr 2023 at 20:05, Alan Bateman <alan.bate...@oracle.com> > wrote: > >> >> On 17/04/2023 15:20, Rob Bygrave wrote: >> >> *:* >> >> >> > *is it reasonable to consider that ServiceLoader is the *only* vector >> by which the implementation class will be instantiated? * >> >> 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 - *the use of requires static for this case is explicit >> and intentional*. >> >> 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. *IF* 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. >> >> >> In your example, module io.avaje.config declares that it provides an >> implementation of io.avaje.inject.spi.PropertyRequiresPlugin. There is >> nothing to connect this to `requires static io.avaje.inject`. The module >> system would need to search "far and wide" for io.avaje.inject to see if >> exports io.avaje.inject.spi 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, `requires static >> io.avaje.inject` >> does not convey to the module system that io.avaje.inject exports >> packages with service types. >> >> 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. >> >> -Alan >> >