javacompiler-errorsjava-9java-modulemodule-path

Java 9 error: not in a module on the module source path


Project structure

I have a project written in Java 8 and I want to update it to Java 9. So I separated the classes into 2 separate modules. Modules:

The file tree looks like:

.
├── org.ggp.base/
│   ├── build.gradle
│   └── src/
│       └── main/
│           ├── java/
│           │   ├── external/
│           │   │   └── JSON/
│           │   │       ├── JSONArray.java
│           │   │       └── JSONObject.java
│           │   ├── META-INF/
│           │   │   └── MANIFEST.MF
│           │   ├── module-info.java
│           │   └── org/
│           │       └── ggp/
│           │           └── base/
│           │               └── util/
│           │                   ├── statemachine/
│           │                   │   ├── MachineState.java
│           │                   │   └── StateMachine.java
│           │                   └── symbol/
│           └── resources/
│               └── org/
│                   └── ggp/
│                       └── base/
└── pl.edu.prz.klopusz/
    └── dolar-app/
        └── src/
            └── main/
                └── java/
                    ├── module-info.java
                    └── pl/
                        └── edu/
                            └── prz/
                                └── klopusz/
                                    └── utilities/
                                        └── decorators
                                          └──StateMachineDecorator.java

The contents of module-info.java files is the following:

org.ggp.base/src/main/java/module-info.java
module org.ggp.base {
    requires guava;
    requires reflections;
    requires jdk.httpserver;

    uses org.ggp.base.util.statemachine.StateMachine;

    exports org.ggp.base;
}
pl.edu.prz.klopusz/dolar-app/src/main/java/module-info.java
module pl.edu.prz.klopusz {
    requires org.ggp.base;

    provides org.ggp.base.util.statemachine.StateMachine
        with pl.edu.prz.klopusz.utilities.decorators.StateMachineDecorator;
}

Compilation

I try to compile the project, using the following command:

javac -d out \
  --module-source-path org.ggp.base/src/main/java:pl.edu.prz.klopusz/dolar-app/src/main/java \
  $(find org.ggp.base/src/main/java -name *.java) \
  $(find pl.edu.prz.klopusz/dolar-app/src/main/java -name *.java)

Errors

I get the following error:

org.ggp.base/src/main/java/module-info.java:1:

error: module not found on module source path
module org.ggp.base {

And 99 other errors for the classes inside org.ggp.base package, each is like:

org.ggp.base/src/main/java/external/JSON/JSONObject.java:1:

error: not in a module on the module source path
package external.JSON;

or

org.ggp.base/src/main/java/org/ggp/base/validator/OPNFValidator.java:1:

error: not in a module on the module source path
package org.ggp.base.validator;

What I want

I want to get rid of the errors and compile the project. I don't have to preserve the directory structure, but when I put it all together, with 2 module-info.java files, the compiler complainted about multiple modules. I can have it done by IntelliJ IDEA, I don't mind and I tried. But I don't know what is happening behind the scenes, and I don't know how to handle the errors either (Package is empty: org.ggp.base).

Package is empty: org.ggp.base

What I've already found

It was hard to find a documentation about --module-source-path switch in javac command. This site is what I found. It says:

if you arrange the code in your modules such that you put the code for a module in an enclosing directory named for the module, the module source path becomes more like a simple path, as in
--module-source-path Users/Me/MyProject/src
or if it is in multiple projects, use
    --module-source-path 
        /Users/Me/MyProject/src:/Users/Me/MyOtherProject/src

And for Windows use backslashes and semicolons, but I'm using Linux anyway.

There is also a comment to an issue on OpenJDK bugs site, with the same error as mine, but I guess it remains unsolved.

UPDATE

-verbose switch

I added -verbose switch at the end of command. That is a part of what compiler says:

[parsing started SimpleFileObject[/home/sensitive/org.ggp.base/src/main/java/module-info.java]]
[parsing started SimpleFileObject[/home/sensitive/org.ggp.base/src/main/java/org/ggp/base/util/statemachine/MachineState.java]]
[parsing started SimpleFileObject[/home/sensitive/pl.edu.prz.klopusz/dolar-app/src/main/java/module-info.java]]
[parsing started SimpleFileObject[/home/sensitive/pl.edu.prz.klopusz/dolar-app/src/main/java/pl/edu/prz/klopusz/utilities/decorators/StateMachineDecorator.java]]
org.ggp.base/src/main/java/org/ggp/base/util/statemachine/MachineState.java:1: error: not in a module on the module source path
package org.ggp.base.util.statemachine;
^
[loading /modules/jdk.httpserver/module-info.class]
[loading /modules/java.base/module-info.class]
[total 263ms]
100 errors

So, I think this is not a fault of the path in --module-source-path switch (the same behavior happens with *src/main/java pointed out by @StephanHerrmann). It reads all the java sources it should read. There's no problem with sources in the pl.edu.prz.klopusz module. These are the first lines of org.ggp.base.util.statemachine.MachineState:

package org.ggp.base.util.statemachine;

import org.ggp.base.util.gdl.grammar.GdlSentence;

import java.util.HashSet;
import java.util.Set;

public class MachineState {
    //...
}

Solution

  • As per JEP 261 the --module-source-path option (for compilation in "multi-module mode") must point to a directory that holds one subdirectory for each contained module, where the directory name must equal the module name.

    To accommodate layouts where sources are not directly contained in the module directory, the option supports patterns where the token * can be used to represent the module name in any part of the path such as in "./*/src/main/java/", which will find the module my.mod1 in ./my.mod1/src/main/java/module-info.java etc.

    JEP 261 does not mention any contraints on where in the pattern * may occur, but apparently javac doesn't like patterns starting with *. This may or may not be intentional.

    Slightly related, I might add that in a previous discussion I was informed that JEP 261 contains outdated information, but my question whether and where this specification would be maintained after the JEP was completed, produced no answer. The javac manual entry is not the place that gives sufficient details for options like --module-source-path.