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

3

10

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:

  • org.ggp.base with module-info.java in the directory org.ggp.base/src/main/java. Its build was automated with Gradle before I started the update to Java 9. The module uses an abstract class implementation included in pl.edu.prz.klopusz module.
  • pl.edu.prz.klopusz in the directory pl.edu.prz.klopusz/dolar-app/src/main/java. I want to automate its build using Maven. The module requires org.ggp.base module.

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 {
    //...
}
Goines answered 25/3, 2018 at 13:46 Comment(7)
I think --module-source-path want to find directories named like the modules at first level. OTOH, if I understand JEP 261 correctly, you could perhaps use a pattern like */src/main/java where * would represent the module name. I haven't tried this, though.Cess
@StephanHerrmann, it doesn't matter if I use */src/main/java or org.ggp.base/src/main/java:pl.edu.prz.klopusz/dolar-app/src/main/java.Aesculapius
your directory layout doesn't exactly fit to the */src/main/java pattern, because of the extra dolar-app intermediate directory, which prevents matching to the module name.Cess
After I removed dolar-app folder and spliced pl.edu.prz.klopusz and src, I used pattern './*/src/main/java'. Neither */src/main/java nor '*/src/main/java' nor org.ggp.base/src/main/java:pl.edu.prz.klopusz/src/main/java worked. After I used the right pattern, errors disappeared. So I guess you can make an answer out of it and I will accept it.Aesculapius
The accepted answer doesn't say what's the exact javac command should look like, neither do you. For completeness sake, it is javac -d out --module-source-path "./*/src/main/java/" $(find . -name "*.java"), right?Buffet
@AbhijitSarkar almost. For some reason, I have to use $(find org.ggp.base/src/main/java -name *.java) $(find pl.edu.prz.klopusz/src/main/java -name *.java), because simple search in current dir find . doesn't work. I will add it to the answer stackoverflow.com/review/suggested-edits/21296807.Aesculapius
I don't understand why the find like I showed won't simply work; it has nothing to do with javac. I think you're doing something wrong with the find. Your edit was rejected for a different reason, I'll post my comment as an answer.Buffet
C
20

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.

Cess answered 28/3, 2018 at 21:23 Comment(0)
B
8

For completeness sake, the complete javac command is as follows:

javac -d out --module-source-path "./*/src/main/java/" $(find . -name "*.java")

Based on the official tutorial from OpenJDK (slightly modified directory structure shown below), and OpenJDK version "11.0.1", the above command javac works for me:

.
├── com.greetings
│   └── src
│       └── main
│           └── java
│               ├── com
│               │   └── greetings
│               │       └── Main.java
│               └── module-info.java
├── org.astro
│   └── src
│       └── main
│           └── java
│               ├── module-info.java
│               └── org
│                   └── astro
│                       └── World.java
├── out
│   ├── classes
│   │   ├── com.greetings
│   │   │   ├── com
│   │   │   │   └── greetings
│   │   │   │       └── Main.class
│   │   │   └── module-info.class
│   │   └── org.astro
│   │       ├── module-info.class
│   │       └── org
│   │           └── astro
│   │               └── World.class
│   └── lib
│       ├── com.greetings.jar
│       └── [email protected]
Buffet answered 1/11, 2018 at 17:52 Comment(3)
Do you know how to write javac -d out --module-source-path "./*/src/main/java/" $(find . -name "*.java") using Windows not Linux/Mac OS ?Advice
@Advice I believe powershell might provide a more useful set of command line utilities that mimic the Unix find command. Otherwise, you can certainly install a bash (or other) shell into windows. I think Cygwin is the general/GNU implementation, though I simply use the toolkit and shell provided by the git tools for windows. That bash shell (which I suspect is cygwin anyway) works just fine and has "find" and most of the other tools. Learn bash, you'll never look back :)Mauve
It's an old question but just in case anyone stumbles upon this: You should be able to do in Windows cmd: dir /s /b *.java > mySourceFiles.txt & javac -d out --module-source-path ".*\src\main\java\" @sourceFiles.txt &del mySourceFiles.txtBobseine
K
0

If you want to be more explicit about the module source paths (in some cases where you cannot specify a pattern in regex), there is a module specific form for --module-source-path flag as documented in https://docs.oracle.com/en/java/javase/17/docs/specs/man/javac.html#module-specific-form.

javac -d out -m org.ggp.base,pl.edu.prz.klopusz --module-source-path org.ggp.base=org.ggp.base/src/main/java --module-source-path pl.edu.prz.klopusz=pl.edu.prz.klopusz/dolar-app/src/main/java
Kirit answered 24/3, 2024 at 3:31 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.