I have a relatively straightforward modular project, and I’ve already set all of the options that I’ve found in the documentation as well as in different answers or articles such as How to force gradle to add dependencies to the module path instead of the class path in eclipse? and others.
I’m getting a module not found exception:
java.lang.module.FindException: Module gdx.backend.lwjgl not found, required by com.myproject.client
I only get this exception when running my application through gradle’s application:run task. When I run it in IntelliJ or using the runtime image generated by the Badass JLink plugin, everything runs fine. After hours of debugging and building command lines by hand I was able to figure out that the difference between a correctly started program and what gradle does, is that everything else starts the program using the –module-path option while Gradle INSISTS on producing the following command line, no matter what I do in my build.gradle files:
Starting process 'command 'C:Toolsjavabinjava.exe''. Working directory: C:repospv-coremasterpv-client Command: C:Toolsjavabinjava.exe -Dfile.encoding=windows-1252 -Duser.country=FR -Duser.language=fr -Duser.variant -cp C:Usersaccou.gradlecachesmodules-2files-2.1com.badlogicgames.gdxgdx-backend-lwjgl1.9.113c094feb74e2aef14e30e988326612ee75387c8fgdx-backend-lwjgl-1.9.11.jar;[...] --module com.myproject.client/com.myproject.client.ClientStarter
Successfully started process 'command 'C:Toolsjavabinjava.exe''
Error occurred during initialization of boot layer
java.lang.module.FindException: Module gdx not found, required by com.myproject.client
My gradle files contain the following:
Root file:
subprojects {
apply plugin: "java"
java {
modularity.inferModulePath = true
}
targetCompatibility = '11'
sourceCompatibility = '11'
repositories {
mavenLocal()
mavenCentral()
maven { url "https://plugins.gradle.org/m2/" }
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
jcenter()
google()
}
test {
useJUnitPlatform()
testLogging {
events 'PASSED', 'FAILED', 'SKIPPED'
}
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.1'
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.3.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.3.1'
}
version = '0.0.1'
ext {
appName = 'MyProject'
gdxVersion = '1.9.11'
box2DLightsVersion = '1.4'
aiVersion = '1.8.0'
artemisVersion = '2.3.0'
junitVersion = '5.4.2'
slf4jVersion = '1.8.0-beta2'
}
}
project(':pv-core') {
dependencies {
}
}
Client project (application):
plugins {
id 'org.beryx.jlink' version '2.22.3'
id 'application'
}
jlink {
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
launcher{
name = 'hello'
jvmArgs = ['-Dlog4j.configurationFile=./log4j2.xml']
}
}
ext.moduleName = 'com.myproject.client'
group = 'com.myproject.client'
//mainClassName = 'com.myproject.client.PVClientStarter'
application {
mainModule = 'com.myproject.client'
mainClass = 'com.myproject.client.ClientStarter'
}
apply plugin: 'java-library'
dependencies {
api "com.badlogicgames.gdx:gdx:$gdxVersion"
api "com.badlogicgames.gdx:gdx-backend-lwjgl:$gdxVersion"
api "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop"
api "com.esotericsoftware.spine:spine-libgdx:3.6.53.1"
api "com.underwaterapps.overlap2druntime:overlap2d-runtime-libgdx:0.1.0"
api "com.kotcrab.vis:vis-ui:1.3.0"
api "net.dermetfan.libgdx-utils:libgdx-utils:0.13.4"
//api "de.tomgrill.gdxfacebook:gdx-facebook-core:1.4.1"
//api "de.tomgrill.gdxdialogs:gdx-dialogs-core:1.2.5"
api "com.github.czyzby:gdx-kiwi:1.9.1.9.6"
api "com.github.czyzby:gdx-lml:1.9.1.9.6"
api "com.github.czyzby:gdx-lml-vis:1.9.1.9.6"
api "de.golfgl.gdxgamesvcs:gdx-gamesvcs-core:1.0.2"
compile "com.badlogicgames.gdx:gdx-ai:$aiVersion"
compile "com.badlogicgames.gdx:gdx-controllers:$gdxVersion"
//compile "com.esotericsoftware:kryo:5.0.0"
compile "kryonet:kryonet:2.21"
testCompile 'org.testng:testng:7.3.0'
}
test {
useTestNG()
//testLogging.showStandardStreams = true
testLogging {
events "passed", "skipped", "failed"
}
}
compileJava {
inputs.property("moduleName", moduleName)
doFirst {
options.compilerArgs += [
'--module-path', classpath.asPath
]
classpath = files()
}
}
Any idea as to how I can possibly (FINALLY) tell gradle to go with –module-path rather than -cp ?!
2
Answers
I think I just figured it out randomly. I kept messing with the gradle files and eventually removed the java blocks containing the statements modularity.inferModulePath = true (despite this being the main advice given in the gradle docs....!), moved up the compileJava block above dependencies and the jlink plugin configuration and it ended up working somehow.
Lots of black magic involved in all this stuff, is the feeling I'm left with after a couple of days of fighting vs modules & gradle tbh..
EDIT: actually I didn't address the root cause of the problem, gradle is still using -cp over --module-path, but the changes I just described above here eventually lead to the gradle successfully launching my application, yet STILL with the -cp option. So I'm still very much interested in having gradle do a proper, JPMS-compliant, module launch (instead of a classpath launch).
The model Gradle introduced for dealing with modules in Java is based on inferring whether or not the current project code is a module or not.
This means that your application needs to have either a
module-info
or aAutomatic-Module-Name
entry in its manifest.Further details in the documentation.