Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:\Users\lolve\Documents\gradle_java\biblio5\src\main\java\module-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:\Users\lolve\Documents\gradle_java\biblio5\src\main\java\module-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?

like image 463
lolveley Avatar asked Aug 19 '18 11:08

lolveley


1 Answers

Update: Gradle 6.4 added basic support for Jigsaw modules. See this sample in the documentation (which also links to other related documentation). Note that the Building Java 9 Modules article linked to in this answer has changed significantly since this answer was posted.


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).

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:

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.

If your Gradle project is an application you also want to read the section covering the run and assemble tasks.

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.

Another Gradle plugin is available: Gradle Modules Plugin.

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:

Changelog

  • Added JPMS module name com.google.common for Guava.

...

However, the most recent version (as of writing this answer) is 26.0.

More information about automatic modules can be found:

  • in the Javadoc of ModuleFinder.of(Path...)
  • this section of The State of the Module System
  • and this Stack Overflow question
like image 50
Slaw Avatar answered Nov 18 '22 16:11

Slaw