Search code examples
javagradlejava-9java-platform-module-systemhdrhistogram

gradle Jigsaw module not found


I try to run a very simple gradle project which uses java 9 modules, but i receive the following error.

/home/vadim/IdeaProjects/test_modules/src/main/java/module-info.java:2: error: module not found: HdrHistogram
    requires HdrHistogram;
             ^

Here is it https://github.com/vad0/test_modules. The main class does basically nothing.

package app;

import org.HdrHistogram.Histogram;

public class RunHdr {
    public static void main(String[] args) {
        final Histogram histogram = new Histogram(5);
        System.out.println(histogram);
    }
}

It uses only one dependency: HdrHistogram. I included this magic command in build.gradle according to official gradle tutorial https://docs.gradle.org/current/samples/sample_java_modules_multi_project.html.

java {
    modularity.inferModulePath = true
}

The whole build.gradle looks like this.

plugins {
    id 'java'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

java {
    modularity.inferModulePath = true
}

dependencies {
    compile group: 'org.hdrhistogram', name: 'HdrHistogram', version: '2.1.12'
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

module.info looks like this

module test.modules.main {
    requires HdrHistogram;
}

I have already read a number of tutorials on Jigsaw and a whole bunch of stackoverflow questions related to it, but still can't make this simple example work. How do i fix it?

Thank you


Solution

  • Unfortunately, gradle does not treat every jar as a module (in simple words). If you want to find out how exactly is gradle building the module-path (as opposed to class-path), you probably want to start from here, specifically at the isModuleJar method. It's pretty easy to understand (though it took me almost two days to set-up gradle and debug the problem out) that the dependency that you are trying to use : gradle says that it is not a module (it isn't wrong, but I am not sure it is correct either). To make it very correct, gradle will add your dependency to the CLASSPATH, but in the very next line: it will not add your dependency to the module-path, because if fails the filter in isModuleJar.

    I do not know if this is a bug or not, or may be this is on purpose, but the solution is easy:

    plugins.withType(JavaPlugin).configureEach {
        java {
            modularity.inferModulePath = true
        }
    
        tasks.withType(JavaCompile) {
            doFirst {
                options.compilerArgs = [
                    '--module-path', classpath.asPath,
                ]
                classpath = files()
            }
        }
    }
    

    you add it to the path, on purpose. I will flag this as a defect and let's see what they have to say.

    EDIT

    Even better, use a plugin that is written by a gradle commiter:

    plugins {
        id 'java'
        id 'de.jjohannes.extra-java-module-info' version "0.1"
    }
    

    And the easiest option on your case is to do :

    extraJavaModuleInfo {
         automaticModule("HdrHistogram-2.1.12.jar", "HdrHistogram")
    }