java 10 gradle project : automatic module not found
java 10 gradle project : automatic module not found
I created a java 10 project with intelliJ, using gradle.
I copied some stuff into it (some "AppFx" class using the library guava and javaFx, and a personal build.gradle file).
I also added a module-info.java file in src/main/java with this content:
module biblio5.main
requires javafx.graphics;
requires javafx.controls;
requires javafx.base;
requires guava;
in which grava is an automatic module.
here is the relevant part of build.gradle:
dependencies
testCompile group: 'junit', name: 'junit', version: '4.12'
compile 'com.google.guava:guava:23.0'
intelliJ can compile the project (using the hammer-like icon) but when I run the compileJava gradle task from intelliJ, I get an error:
13:12:46: Executing task 'compileJava'...
Task :compileJava FAILED C:UserslolveDocumentsgradle_javabiblio5srcmainjavamodule-info.java:5:
error: module not found: guava
requires guava;
^ 1 error
I spent a lot of time on the net but did not manage to find an answer.
thank you
ps: here is the entire build.gradle:
buildscript
dependencies
classpath group: 'de.dynamicfiles.projects.gradle.plugins', name: 'javafx-gradle-plugin', version: '8.8.2'
classpath 'eu.appsatori:gradle-fatjar-plugin:0.3'
repositories
maven url "https://mvnrepository.com/artifact/de.dynamicfiles.projects.gradle.plugins/javafx-gradle-plugin"
mavenCentral()
maven url "https://oss.sonatype.org/content/repositories/snapshots"
jcenter()
plugins
id 'java'
id 'application'
id 'edu.sc.seis.launch4j' version '2.4.4'
apply plugin: 'javafx-gradle-plugin'
apply plugin: 'eu.appsatori.fatjar'
group 'lorry'
version '1'
sourceCompatibility = 1.10
repositories
// Use jcenter for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
maven url "https://mvnrepository.com/artifact/de.dynamicfiles.projects.gradle.plugins/javafx-gradle-plugin"
jcenter()
mavenCentral()
maven url "https://oss.sonatype.org/content/repositories/snapshots"
dependencies
testCompile group: 'junit', name: 'junit', version: '4.12'
compile 'com.google.guava:guava:23.0'
//********************************************************************************************
launch4j
outfile='bibliotek-v3.exe'
mainClassName = 'lorry.AppFx'
icon = "$projectDir\icons\hands2.ico"
copyConfigurable = project.tasks.fatJar.outputs.files
//jar = "lib/$project.tasks.fatJar.archiveName"
//headerType = "console"
jar = "$buildDir\productFatJar\fat.jar"
jar
baseName = 'executable3'
version = ''
manifest
attributes(
'Class-Path': configurations.compile.collect it.getName() .join(' '),
'Main-Class': 'lorry.AppFx'
)
task copyExecutable(type: Copy)
from file("$buildDir\launch4j\bibliotek-v3.exe")
into file("c:\Users\lolve\Documents\gradle_java\produits")
task copyJar(type: Copy)
from file("$buildDir\jfx\app\bibliotek-v3.jar")
into file("c:\Users\lolve\Documents\gradle_java\produits")
task copyFatJar(type: Copy)
from file("$buildDir\productFatJar\fat.jar")
into file("c:\Users\lolve\Documents\gradle_java\produits")
createExe.doLast
tasks.copyExecutable.execute()
task createJar()
doLast
tasks.jfxJar.execute()
tasks.jfxNative.execute()
tasks.copyJar.execute()
jfx
jfxMainAppJarName = "bibliotek-v3.jar"
// minimal requirement for jfxJar-task
mainClass = 'lorry.AppFx'
// minimal requirement for jfxNative-task
vendor = 'lolveley'
fatJar
destinationDir=file("$buildDir\productFatJar")
archiveName="fat.jar"
manifest
attributes(
'Class-Path': configurations.compile.collect it.getName() .join(' '),
'Main-Class': 'lorry.AppFx'
)
task createFats()
doLast
tasks.fatJar.execute()
tasks.copyFatJar.execute()
tasks.createExe.execute()
EDIT
well, I made the change, and now I have "com.google.commons" instead guava in module-info.java, but I still get this error:
Testing started at 14:20 ... 14:20:14: Executing task 'check'...
Task :compileJava FAILED C:UserslolveDocumentsgradle_javabiblio5srcmainjavamodule-info.java:5:
error: module not found: com.google.common
requires com.google.common;
^ 1 error
I changed gradle in intelliJ (the default option - recommended - was "default gradle wrapper") to my local gradle (v4.9), but without any effect.
What do you mean by "compatible with java"? What about try with a java 9 installation?
My bad with the answer, I'd assumed that gradle(if updated) would be compatible with module path for Java9+ modular code. Just by the overview of the above document, this should be one of the section to look into
– nullpointer
Aug 19 at 12:50
thank you, Slaw & nullpointer, adding the short code made it work. I can't mark the answer as accepted as there only remains commentaries, but if s/o make it as an answer, I soon will mark it as accepted.
– lolveley
Aug 19 at 13:16
1 Answer
1
The issue is Gradle still (as of 4.10-rc-2) doesn't have first-class support for Jigsaw modules. All the tasks will use the classpath, not the modulepath, when executing. This obviously will cause issues when trying to create a modular library/application (with module-info.java
).
module-info.java
If you want to use Jigsaw modules in your project you should read Building Java 9 Modules. Your scenario, as @nullpointer mentions, is best covered by this section of the linked document. The takeaway is to add the following to your build.gradle
file:
build.gradle
ext.moduleName = 'your.module'
compileJava
inputs.property('moduleName', moduleName)
doFirst
options.compilerArgs = [
'--module-path', classpath.asPath
]
classpath = files()
They also have sections for modifying the compileTestJava
task (here) and the test
task (here). Personally, I tend to not modify those tasks as testing often requires a lot of reflection which in turn requires a lot of --add-opens
arguments. If you find out that's not true (haven't tried it in a while) or there's a better way, please let me know.
compileTestJava
test
--add-opens
If your Gradle project is an application
you also want to read the section covering the run
and assemble
tasks.
application
run
assemble
There is an experimental Gradle plugin that does all this for you: experimental-jigsaw
. The plugin is limited, however, and there is a fork on GitHub, named chainsaw
, that adds more features. Note: I don't know how maintained either plugin is.
experimental-jigsaw
chainsaw
If you want to watch for updates regarding Jigsaw support in Gradle they maintain an epic on GitHub.
Also, to include what @nullpointer commented, you should be using a version of Guava that includes an Automatic-Module-Name
entry in its manifest. Without this entry (combined with no module-info
) the name of the module is subject to the name of the jar
file; which may change unexpectedly. In other words, the Automatic-Module-Name
entry makes for a better contract regarding the name of an automatic module. The first version that Guava added this entry is 23.2:
Automatic-Module-Name
module-info
jar
Automatic-Module-Name
Changelog
com.google.common
...
However, the most recent version (as of writing this answer) is 26.0.
More information about automatic modules can be found:
ModuleFinder.of(Path...)
Just to add to all of the above. The part about using the updated version of the library shall still make sense, since the explicitly added
Automatic-Module-Name: com.google.common
is a clearer contract to make use of a library as an automatic module.– nullpointer
Aug 19 at 13:59
Automatic-Module-Name: com.google.common
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Gradle, by default, uses the classpath, not the modulepath, when compiling/running. I believe this is causing your problem. See Building Java 9 Modules. Unfortunately, according to that link Gradle still doesn't have first-class support for Jigsaw modules (as of 4.10-rc-2).
– Slaw
Aug 19 at 12:32