Enhancement: Infer module path
oliver-brm opened this issue · 4 comments
In my application, I'm using service modules and separate modules which provide those services. Gradle 7.2 itself is able to infer the module path for the application by looking at the dependencies - service implementations show up as runtime project(...)
dependencies. Example:
dependencies {
implementation project(':greeting-service') // this is the service API
runtimeOnly project(':greeting-provider-fixed') // this is the service implementation
}
I'm using the badass-jlink-plugin:2.24.2
, which however does not infer the module path for those service implementations. It's working fine if I specify the module path in a customImage
declaration. Example:
jlink {
customImage {
appModules = [
'org.example.jpms.hello.main',
'org.example.jpms.hello.greeting.service',
'org.example.jpms.hello.greeting.provider.fixed']
}
}
This can get a bit cumbersome with more and more modules added to the application. Wouldn't it be possible to derive the module path from the application's dependencies? I would be glad to contribute to that feature.
I have pushed a reproducer project here: https://github.com/oliver-brm/jpms-hello.git. To reproduce:
- Remove the
customImage
declaration frombuild.gradle
- Run the
jlink
orjpackage
task - Try to execute
build/image/bin/greeting
, it will print:
Exception in thread "main" java.util.NoSuchElementException: No value present
at java.base/java.util.Optional.orElseThrow(Unknown Source)
at org.example.jpms.hello.main/org.example.jpms.hello.App.main(Unknown Source)
Sorry for the late reply. It would be great if you can contribute to this feature, it's very useful. Thank you for your help!
OK, cool! I would look if I can somehow extract the module path which the java
plugin creates. That would make life a bit easier and it's more predictable for the user what the module path will be. I've never created a plugin for Gradle, nor modified one. So, I'm very happy for any hint how I might start this one.
I sent my message yesterday without having a look at your reproducer project. Now I finally took the time to look at it and realized that I had misunderstood the problem.
There is probably no need to enhance the plugin because jlink itself is able to infer the module path for service implementations when called with the --bind-services
option. So, by putting the following in your build.gradle, your application should work fine:
jlink {
options = ['--bind-services', '--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
launcher {
name = 'greeting'
}
}
Yeah, jlink
's --bind-services
option - its implementation is in my eyes too greedy. It will pull in any implementing module, not only those which I put on the module path via Gradle's dependency mechanism. See also this thread on Stack Overflow.