Artifact with several modules (jdeps errors)

Answered

I create with the ide an app.jar artifact that embeds 3 external libs. 
Each library is a separate java module.

1. the packages of the libs are copied correctly.
2. the program runs correctly.
3. jdeps reports missing modules of the 3 libs.

A look into the jar shows that all packages are present.
One module-info file with the reference to the modules of the app
and the 3 modules of the libs is there.

I think there are two possibilities, either the modules of the 3 libs
are not mentioned in the main module-info file (only embed) or
the jar should have the following directories.

module-info
ModuleA/the.packages.x
ModuleA/module-info
ModuleB/the.packages.x
ModuleB/module-info

Which is the right way and how to set it
I use Idea native Tools (no gradle or maven),

0
11 comments

Hello!

To properly embed external libraries in your JAR file, the module-info file in the main module should reference the required modules, including the three libraries. Each library should have its own module directory structure within the JAR file, like:

module-info
ModuleA/the.packages.x
ModuleA/module-info
ModuleB/the.packages.x
ModuleB/module-info
Make sure the module-info file lists the dependencies correctly, and the JAR should work fine.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

ATT My Results com

0

Hello
Thanks for the clarification. Then I will add the missing module directories manually. 
Is this a bug of the artifact function (ide) that the directory and module-info of the libs 
were not included?

0

Hello, Sandro!

Thank you for reporting this!

Could you please share

  • The exact error message you are getting
  • Your current Artifact configuration
  • If possible, the affected Project(s)
0

Hello Roman

1. the extraction worked as expected. 
FlowTool.jar had all packages of the 3 libs

jar tf FlowTool.jar 
META-INF/MANIFEST.MF
flowtool/core/FlowTool.class
flowtool/actions/FTRunAction.class
...
module-info.class
csvengine/csv/CSVWriter.class
csvengine/csv/CSVType.class
csvengine/csv/CSVParams.class
...
jsonengine/core/JSONStringifier.class
jsonengine/core/JSONException.class
jsonengine/core/JSONArray.class
jsonengine/core/JSONParser.class
...
flow/core/XFRef.class
flow/core/XFScope.class
flow/core/XFModel.class
flow/core/XFBinding.class
...

2. the program runs correctly.
3. run  jdeps FlowTool.jar 

Exception in thread "main" java.lang.module.FindException: Module CSVEngine not found, required by FlowTool
    at java.base/java.lang.module.Resolver.findFail(Resolver.java:893)
    at java.base/java.lang.module.Resolver.resolve(Resolver.java:192)
    at java.base/java.lang.module.Resolver.resolve(Resolver.java:141)
    at java.base/java.lang.module.Configuration.resolve(Configuration.java:421)
    at java.base/java.lang.module.Configuration.resolve(Configuration.java:255)
    at jdk.jdeps/com.sun.tools.jdeps.JdepsConfiguration$Builder.build(JdepsConfiguration.java:564)
    at jdk.jdeps/com.sun.tools.jdeps.JdepsTask.buildConfig(JdepsTask.java:603)
    at jdk.jdeps/com.sun.tools.jdeps.JdepsTask.run(JdepsTask.java:557)
    at jdk.jdeps/com.sun.tools.jdeps.JdepsTask.run(JdepsTask.java:533)
    at jdk.jdeps/com.sun.tools.jdeps.Main.main(Main.java:49) 

4. Only one modul-info was included
module FlowTool
{
    requires JSONEngine;
    requires CSVEngine;
    requires FlowEngine;

    exports flowtool.core;
    exports flowtool.actions;
}

5. Proposed solution
├── CSVEngine/
│ ├── com/example/one 
│ │ └── MyClass1.java
│ └── module-info.java
├── JSONEngine/ 
│ ├── com/example/two
│ │ └── MyClass2.java
│ │ └── MyClass3.java
│ └── module-info.java
└── module-info.java

 

 

 

0

Sandro Roellin Thank you for sharing the details!

I believe this issue occurs due to Java's Modules system expecting only one Module per JAR.

So, while this JAR is functional, I don't think it is compatible with the Java Modules system.

0

Hello Roman

i have now tested this and created a jar by hand. 
i have copied the  original output from  ide “out/production/” from each lib into a jar
and the FlowTool (App) too. 

It works no jdeps error. :)
But when the program is running, “class not found” problems occur. :(

├── CSVEngine/
│ ├── csvengine/core/AnyClass.class …
│ └── module-info.java
├── JSONEngine/ 
│ ├── jsonengine/core/AnyClass.class…
│ └── module-info.java
├── flowtool/package/AnyClass.class..
├── module-info.java

Solution for one Java Module? (Artifact)
if jar really do not support this multi module structures (Edward357johnson)
you have to create the module-info without the “requires CSVEngine …”
and copy only the packages (like the ide now)
but the ide does not allow this.

if “requires” is set jdeps not work.
i have also tested this with the lib jars too,
whenever in the module-info another lib is set as “requires” 
it gives errors.
 

0

Sandro Roellin Thank you for the update!

I believe that still supports the idea that each JAR should only contain one Module (see Stack Overflow, for instance).

You can create a JAR with multiple module-info.java files in it and it will be technically “correct” (i. e. jdeps will be able to resolve it), but as you can see it may not work properly.

The correct way to handle a Project like yours is to create a separate JAR for each Module and then run it like this:

java --module-path libs/modules --module org.example.core/org.example.Main

where

libs/modules is the directory, where other Modules' JARs are located

org.example.core/org.example.Main is the Module that runs your app and the Class that starts

0

I think you are right - one module per jar is the solution. 
But one question is still not answered: 
the result of the standard jar action is not jdeps compliant - even with 1 module:
1. all libs are copied the app run correct [OK]
2. why is the app module-info not corrected when saving? [fail]
only the line “require libxyz” of the lib should be removed automatically - 
the lib was embedded after all

0

Sandro Roellin I believe for the JAR to be jdeps compliant by default every Java Module should be a separate IDEA Project, not an IDEA Module.

0

We simply don't understand each other.
1. each of my libraries is an IDEA project, I create a jar file from each project.
2. the main application used these jars as libraries.
3. if i want to use the libraries i have to make an entry in main module.info - right?
4. now I want to copy everything together with artifact action
5. if I run jdeps - error.
6. this error only appears because “requires libxyz” in main moduleinfo - 
but i cant remove it (see #3)

i hope i'm not talking to a AI bot here…

0

Sandro Roellin This sounds like the same problem we've already discussed: your app is Modular, so it should produce a set of separate JARs (one for each Module), but you seem to package them all into a same Artifact.

When you run jdeps against this JAR it sees module-info.class and assumes the JAR is Modular, so it tries to look for other Modules (JAR files), but there are none - everything is packaged into a single Artifact, hence the error.

If you want the app to be distributed as a single file, I think you should look into creating an installer (i. e. jpackage).

 

0

Please sign in to leave a comment.