Gradle doesn't add modules to module-path during compile


(Sverre Moe) #1

I started a new project, which is modularized.
It contains 4 dependencies, two of which is also modularized.

compile group: 'org.controlsfx', name: 'controlsfx', version: '9.0.0'
compile group: 'com.jfoenix', name: 'jfoenix', version: '9.0.4'
compile group: 'org.jfxtras', name: 'jfxtras-controls', version: '9.0-r1'
compile group: 'com.google.protobuf', name: 'protobuf-java', version: '3.5.1'
testCompile group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.2.0'
testRuntime group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version:'5.2.0'

My module-info.java

requires javafx.controls;
requires javafx.fxml;
requires javafx.web;
requires javafx.graphics;

/* Named modules */
requires jfxtras.controls;
requires com.jfoenix;

/* Automatic modules */
requires controlsfx;
requires protobuf.java;

Gradle will not compile as it complains of missing modules for all of these 4 dependencies.

So adding these to build.gradle solves that:

compileJava {
    inputs.property("moduleName", moduleName)
    doFirst {
        options.compilerArgs = [
            '--module-path', classpath.asPath,
        ]
        classpath = files()
    }
}

compileTestJava {
    inputs.property("moduleName", moduleName)
    doFirst {
        options.compilerArgs = [
            '--module-path', classpath.asPath,
            '--add-modules', 'org.junit.jupiter.api',
            '--add-reads', "$moduleName=org.junit.jupiter.api",
            '--patch-module', "$moduleName=" + files(sourceSets.test.java.srcDirs).asPath,
        ]
        classpath = files()
    }
}

As taken from the tutorial:

https://guides.gradle.org/building-java-9-modules/#modify_the_code_compilejava_code_task_to_produce_a_module

However it seems unnecessary boilerplate code. I moved from Maven to Gradle because I liked the Groovy coding, and how much smaller my build.gradle was compared to pom.xml. My pom.xml was ~900 lines and my equivalent build.gradle only 350 lines.

This works out of the box with Maven without any extra configuration messing with the modulepath. So I expected it to work seamlessly with Gradle as well.

It seems Gradle support for Java 9 is not complete. Now that Java 11 is soon here this should have been ironed out. We should expect same behaviour for modulepath as we have to classpath. If a module add all dependencies to modulepath, else add all dependencies to classpath.

This works fine with the application plugin without having to specify module-path. I can execute gradle run and the application starts up.
I am able to run without the run configuration in the Guide
https://guides.gradle.org/building-java-9-modules/#modify_the_code_run_code_task_to_use_modules


The guide states that gradle support for Java 9 modules are lacking:

While Gradle does not yet support building Java 9 modules as a first-class feature of the Java plugins, an experimental plugin is available to allow you to experiment with Java 9 modules on your projects.


I found this piece of information:
https://github.com/elastic/elasticsearch/issues/28984

“Maven provides the jar to JDK ModuleFinder
If the ModuleFinder considers the Jar as a module, Maven adds the Jar to --module-path
If the ModuleFinder does not consider the Jar as a module (i.e. elasticsearch), Maven adds it to -classpath”

“Gradle doesn’t make any kind of jigsaw module autodetection.
By default, even in Java 9, Gradle will put all dependencies into the classpath.
This is confirmed by the tutorial that expects us to populate the --module-path and override -classpath manually.”


Different Maven and Gradle execution of Java 9+ Modular Junit 5 tests
(Sverre Moe) #2

Java Module Madness is here now that JavaFX 11 has been released.
I have started using it as dependencies.

Already before JavaFX 11 I had to set
‘–module-path’, classpath.asPath
for compileJava, compileTestJava, javadoc and test.

I didn’t however need to do it for application plugin run task. Until now.
With the JavaFX modules I have now also needed to --add-module for each.

This Gradle configuration has grown. In this regard it no longer has an advantage over Maven, which doesn’t need to set all these flags.

I really hope Gradle is working on making Java 9 module support better, and without all this boilerplate configuration.

compileJava {
    inputs.property("moduleName", moduleName)
    doFirst {
        options.compilerArgs = [
            '--module-path', classpath.asPath,
            '--add-modules', 'javafx.controls',
            '--add-modules', 'javafx.fxml',
            '--add-modules', 'javafx.web',
            '--add-modules', 'javafx.graphics',
            '--add-modules', 'javafx.media'
        ]
        classpath = files()
    }
}

compileTestJava {
    inputs.property("moduleName", moduleName)
    doFirst {
        options.compilerArgs = [
            '--module-path', classpath.asPath,
            '--add-modules', 'javafx.controls',
            '--add-modules', 'javafx.fxml',
            '--add-modules', 'javafx.web',
            '--add-modules', 'javafx.graphics',
            '--add-modules', 'javafx.media',
            '--add-modules', 'org.junit.jupiter.api',
            '--add-reads', "$moduleName=org.junit.jupiter.api",
            '--patch-module', "$moduleName=" + files(sourceSets.test.java.srcDirs).asPath,
        ]
        classpath = files()
    }
}

run {
    doFirst {
        jvmArgs = [
                '--module-path', classpath.asPath,
                '--add-modules', 'javafx.controls',
                '--add-modules', 'javafx.fxml',
                '--add-modules', 'javafx.web',
                '--add-modules', 'javafx.graphics',
                '--add-modules', 'javafx.media'
        ]
    }
}

javadoc {
    inputs.property("moduleName", moduleName)
    doFirst {
        exclude "**/module-info.java"
        options.addStringOption('-module-path', classpath.asPath)
        options.addStringOption('-add-modules', 'javafx.controls')
        options.addStringOption('-add-modules', 'javafx.fxml')
        options.addStringOption('-add-modules', 'javafx.web')
        options.addStringOption('-add-modules', 'javafx.graphics')
        options.addStringOption('-add-modules', 'javafx.media')
        options.addStringOption('-class-path', "")
        options.addBooleanOption('html5', true)
        options.addBooleanOption('verbose', true)
    }
}

test {
    useJUnitPlatform()

    doFirst {
        jvmArgs = [
            '--module-path', classpath.asPath,
            '--add-modules', 'javafx.controls',
            '--add-modules', 'javafx.fxml',
            '--add-modules', 'javafx.web',
            '--add-modules', 'javafx.graphics',
            '--add-modules', 'javafx.media'
        ]
    }
}

Loading resources files in Java 11