I'm using Gradle (4.10.3, but I've tried most versions up through 5.4.1) with JDK 12.0.1 and the org.beryx.jlink
plugin (2.10.4), but am running into this error every time I attempt to create the jlink image:
-> Task :createMergedModule
Cannot derive uses clause from service loader invocation in: com/fasterxml/jackson/databind/ObjectMapper$2.run().
Cannot derive uses clause from service loader invocation in: com/fasterxml/jackson/databind/ObjectMapper.secureGetServiceLoader().
Cannot derive uses clause from service loader invocation in: org/apache/commons/compress/utils/ServiceLoaderIterator.().
C:\Users\MyName\IdeaProjects\myapp\build\jlinkbase\tmpjars\myapp.merged.module\module-info.java:393: error: the service implementation does not have a default constructor: XBeansXPath provides org.apache.xmlbeans.impl.store.PathDelegate.SelectPathInterface with org.apache.xmlbeans.impl.xpath.saxon.XBeansXPath;
C:\Users\MyName\IdeaProjects\myapp\build\jlinkbase\tmpjars\myapp.merged.module\module-info.java:394: error: the service implementation does not have a default constructor: XBeansXQuery provides org.apache.xmlbeans.impl.store.QueryDelegate.QueryInterface with org.apache.xmlbeans.impl.xquery.saxon.XBeansXQuery; 2 errors
-> Task :createMergedModule FAILED
When I click through to the lines throwing the errors in the merged module-info.java
, it points to these two:
provides org.apache.xmlbeans.impl.store.PathDelegate.SelectPathInterface with org.apache.xmlbeans.impl.xpath.saxon.XBeansXPath;
provides org.apache.xmlbeans.impl.store.QueryDelegate.QueryInterface with org.apache.xmlbeans.impl.xquery.saxon.XBeansXQuery;
My build.gradle
file looks like this:
plugins {
id 'application'
id 'idea'
id 'java'
id 'org.openjfx.javafxplugin' version '0.0.7'
id 'org.beryx.jlink' version '2.10.4'
}
repositories {
mavenCentral()
}
dependencies {
compile 'org.apache.commons:commons-csv:1.6'
compile 'org.apache.poi:poi-ooxml:4.1.0'
compile 'com.fasterxml.jackson.core:jackson-core:2.9.9'
compile 'com.fasterxml.jackson.core:jackson-annotations:2.9.9'
compile 'com.fasterxml.jackson.core:jackson-databind:2.9.9'
testCompile 'org.junit.jupiter:junit-jupiter-api:5.5.0-M1'
testRuntime 'org.junit.jupiter:junit-jupiter-engine:5.5.0-M1'
}
// ### Application plugin settings
application {
mainClassName = "$moduleName/path.to.myapp"
}
// ### Idea plugin settings
idea {
module {
outputDir = file("out/production/classes")
}
}
// ### Java plugin settings
sourceCompatibility = JavaVersion.VERSION_11
compileJava {
options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
}
test {
useJUnitPlatform()
testLogging {
events 'PASSED', 'FAILED', 'SKIPPED'
}
}
// ### JavaFX plugin settings
javafx {
version = "12.0.1"
modules = ['javafx.controls', 'javafx.fxml']
}
// ### jlink plugin settings
jlink {
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
launcher {
name = 'myapp'
}
}
Any ideas on how I can address this?
The following possible solution is based just on your build file, without knowing about your module-info or the project's code, so it might not work.
It is also based on this issue at the jlink plugin's repository.
First, let me explain how this plugin works: since the (JDK) jlink
tool doesn't allow non-modular dependencies, the plugin will try to collect all of them and create on the fly a module, that can be added to the module-path. This module is named $yourModuleName.mergedModule
.
Now I'm adding your dependencies to a simple JavaFX project. When I run ./gradlew jlink
I get the same errors you have posted. If you check the errors:
myapp\build\jlinkbase\tmpjars\myapp.merged.module\module-info.java:394: error
This shows that the created module is named myapp.merged.module
, and that it has a module-info
descriptor. If you open it you will see all the exports
(the module will export every package of the dependencies by default), the requires
and the provides
:
open module myapp.merged.module {
exports com.fasterxml.jackson.annotation;
exports com.fasterxml.jackson.core;
exports com.fasterxml.jackson.core.async;
...
exports schemaorg_apache_xmlbeans.system.sXMLTOOLS;
requires java.xml.crypto;
requires java.logging;
requires java.sql;
requires java.xml;
requires java.desktop;
requires java.security.jgss;
requires jdk.javadoc;
uses java.nio.file.spi.FileSystemProvider;
provides com.fasterxml.jackson.core.JsonFactory with com.fasterxml.jackson.core.JsonFactory;
provides com.fasterxml.jackson.core.ObjectCodec with com.fasterxml.jackson.databind.ObjectMapper;
provides org.apache.xmlbeans.impl.store.QueryDelegate.QueryInterface with org.apache.xmlbeans.impl.xquery.saxon.XBeansXQuery;
provides org.apache.xmlbeans.impl.store.PathDelegate.SelectPathInterface with org.apache.xmlbeans.impl.xpath.saxon.XBeansXPath;
}
So now the question is: should you add some more requirements to your own module? The answer is explained here: that will increase unnecessary your project's size. A better way is to use the mergedModule
script block:
The mergedModule block allows you to configure the module descriptor of the merged module
And:
the module descriptor is created using the algorithm implemented by the
suggestMergedModuleInfo
task.
If you run ./gradlew suggestMergedModuleInfo
you will basically get the same contents for the merged module descriptor as above.
A possible solution is to start just adding some requires to the merged module descriptor, and try again.
I started with:
jlink {
mergedModule {
requires "java.xml"
}
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
launcher {
name = 'myapp'
}
}
and I could run ./gradlew jlink
successfully.
If you check the merged module descriptor now, it will look like:
open module myapp.merged.module {
requires java.xml;
exports com.fasterxml.jackson.annotation;
exports com.fasterxml.jackson.core;
exports com.fasterxml.jackson.core.async;
...
exports schemaorg_apache_xmlbeans.system.sXMLTOOLS;
}
containing only the explicit requires
, all the exports, but without provides
, so the errors will be gone.
Since I don't have your code, I can't say if this will work for you, but it did for me with the same dependencies.