This simple project should respond to ./gradlew run
with Hello World!
.
Instead, it raises NoSuchElementException
.
The cause is Gradle’s decision to put api
and impl
in the class path instead of the module path.
Gradle seems to make this decision based on the fact that app
is not a module.
This decision breaks the service loader mechanism.
impl
declares it’s provided services in its module definition.
It is meant to be put in the module path, not the class path.
One may be tempted to avoid this problem by redeclaring impl
's services in META-INF/services
.
This way, when impl
be put in the class path, the service loader is satisfied.
However, api
module designers intended for the spi
package to have restricted access to impl
only.
Allowing api
and impl
in the class path makes this restriction meaningless.
To enforce this restriction, api
and impl
must require the module path.
Currently, one cannot apply this kind of architecture with non-modular Gradle applications.