I wrote a Java module a.b.c and another module d.e.f that requires a.b.c. I'm using IntelliJ.
First module's module-info.java:
module a.b.c {
exports a.b.c;
requires org.jfree.jfreechart;
requires commons.cli;
requires java.desktop;
requires java.net.http;
}
Second module's module-info.java:
module d.e.f {
requires a.b.c;
requires org.json;
}
Both modules compile. When I run d.e.f, I get the following error.
java.lang.module.ResolutionException: Module a.b.c contains package org.jfree.chart.ui, module org.jfree.jfreechart exports package org.jfree.chart.ui to a.b.c
These modules aren't split as there is no redundant package between them.
What does this message mean?
How do I resolve it?
I received the ResolutionException error because my IntelliJ project was not set up correctly. The best guidance I found was at Java 9 Modules with IntelliJ IDE Quick Start. Both modules now run without any compile- or run-time errors.
Related
I am making a JavaFX application, and want to use javafaker (https://github.com/DiUS/java-faker) to create some testdata while I am developing the application. The problem is that when I import the package: import com.github.javafaker.Faker;, the compiler complains and warns me with:
The type com.github.javafaker.Faker is not accessible Java(16778666).
So far I've figured out that it's because I don't have javafaker required in module-info.java. If i delete module-info.java the problem goes away, however, I am not able to run the application. I get the error:
Error: JavaFX runtime components are missing, and are required to run this application.
I suppose this is because module-info.java is gone.
I have tried requiring javafaker like this in module-info.java:
open module my_project {
requires javafx.base;
requires javafx.controls;
requires javafx.fxml;
requires javafx.graphics;
requires com.github.javafaker;
}
However, I get the error:
com.github.javafaker cannot be resolved to a module Java(8389908).
What is the proper way to require such a package? I have tried searching for solutions, but I haven't been able to convert the solutions to something I can use for this problem.
I am using maven, and I have added javafaker as a dependency.
On a project with multi modules, we want to use picocli with jline to build a console app. For each module we created a module-info.java. But with picocli we are not able to compile our application. we have tons of errors like
module info.picocli.shell.jline3 reads package org.jline.console from both org.jline.console and org.jline
module info.picocli.shell.jline3 reads package org.jline.console.impl from both org.jline.console and org.jline
module info.picocli.shell.jline3 reads package org.jline.keymap from both org.jline.reader and org.jline
the unnamed module reads package org.jline.keymap from both org.jline.reader and org.jline
the unnamed module reads package org.jline.reader from both org.jline.reader and org.jline
...
we included following dependencies with gradle
dependencies {
implementation 'org.fusesource.jansi:jansi:2.3.4'
implementation 'info.picocli:picocli:4.6.1'
implementation 'info.picocli:picocli-shell-jline3:4.6.1'
annotationProcessor 'info.picocli:picocli-codegen:4.6.1'
}
and our java-modules.info looks like
module foo.bar.app {
exports foo.bar.app;
requires info.picocli;
requires info.picocli.shell.jline3;
requires org.jline;
requires org.fusesource.jansi;
}
I followed the advice in FAQ https://github.com/remkop/picocli/wiki/Java-9-modules but it hasn't worked out.
If we disable java modules, the application can be built and runs as it should.
Does anybody had a similar issue and knows some advice?
Problem
How do you create a java library jar that both:
is java module (has module-info)
has a depending legacy (non-module) jar. (like commons-exec)?
The dependency is an implementation detail - should not be exported.
Sources
Having the following build.gradle (using gradle-6.8):
plugins {
id 'java-library'
}
group = 'test'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '15'
repositories {
mavenCentral()
}
java {
modularity.inferModulePath = true
}
dependencies {
implementation 'org.apache.commons:commons-exec:1.3'
}
and the following module-info.java:
module test.module {
requires commons.exec;
}
Errors
I'm getting the following compile error:
module-info.java:2: error: module not found: commons.exec
requires commons.exec;
^
If I don't include requires commons.exec then the error becomes:
error: package org.apache.commons.exec is not visible
import org.apache.commons.exec.CommandLine;
^
(package org.apache.commons.exec is declared in the unnamed module,
but module test.module does not read it)
commons.exec module name?
Running jar --file=commons-exec-1.3.jar --describe-module does output:
No module descriptor found. Derived automatic module.
commons.exec#1.3 automatic
requires java.base mandated
contains org.apache.commons.exec
contains org.apache.commons.exec.environment
contains org.apache.commons.exec.launcher
contains org.apache.commons.exec.util
So commons.exec looks like a valid module name for commons-exec-1.3.jar. Intelij Idea seem to agree and does auto-complete it in module-info.java. Though it fails at build time.
I managed to overcome the same issue using java-module-info plugin.
This plugin allows you to add module information to a Java library
that does not have any. If you do that, you can give it a proper
module name and Gradle can pick it up to put it on the module path
during compilation, testing and execution.
plugins {
id 'java-library'
id("de.jjohannes.extra-java-module-info") version "0.6"
}
Add this section into your build.gradle to add the commons-exec module information
extraJavaModuleInfo {
module("commons-exec-1.3.jar", "org.apache.commons.exec", "1.3") {
exports("org.apache.commons.exec")
}
}
Add requires org.apache.commons.exec; to your module-info.java
EDIT 1:
Gradle 7.0 comes with full support for the Java module system. Users can now build, test, and run Java modules via Gradle. The mere presence of module-info.java will let Gradle infer that your jar is a module and has to be put on the modulepath instead of the traditional classpath.
Using libraries that are not modules
I have 2 libraries, which I have migrated to Java 10 and used module system.
First thing which makes me worry is that I had a lot of errors like:
Error:java: the unnamed module reads package org.aspectj.internal.lang.reflect from both aspectjrt and org.aspectj.weaver. To fix that, I have added requires org.aspectj.weaver; to module info. Actually I had to put there lot of other things which I don't use, but e.g. Spring uses. Only then I was able to compile it.
So in the end, my module-info for the first library looks like this:
module my.lib1 {
requires spring.context;
requires spring.core;
requires spring.context.support;
requires spring.beans;
requires org.aspectj.weaver;
requires slf4j.api;
requires metrics.core;
requires com.fasterxml.jackson.databind;
requires java.validation;
requires org.hibernate.validator;
requires javax.el;
exports my.lib1;
}
For the second library I also had to add a lot of libs that are used by dependencies, not me:
module my.lib2 {
requires org.hibernate.orm.core;
requires java.sql;
requires java.persistence;
requires spring.context;
requires spring.tx;
requires spring.orm;
requires spring.data.jpa;
requires spring.beans;
requires HikariCP;
requires metrics.core;
requires slf4j.api;
requires spring.core;
exports my.lib2;
}
Both libs are compiling now. I put them in my local mvn repo and started third project which depends on this two.
module my.project {
requires my.lib1;
requires my.lib2;
}
And now I got the same error... Error:java: the unnamed module reads package org.aspectj.internal.lang.reflect from both aspectjrt and org.aspectj.weaver, but this time, adding requires org.aspectj.weaver; doesn't help. I have noticed when I put only one of the libs in the module (not both together, but one lib1 or lib2) it works.
Is it normal that I have to put different libs in my module-info which are used not by my but by other dependencies? (e.g. shouldn't it be Spring's responsibility to require aspectj?).
And the most important thing: how do I fix the problem with my project which depends on my two libs?
I have noticed when I put only one of the libs in the module (not both together, but one lib1 or lib2) it works.
Using the module system, a package may only be offered by a single module in your current module graph. This is one of the main reasons for the introduction of the module system: avoidance of ambiguous dependencies (as they occur on the classic class path; called split packages). And that's why it works with only one of your modules.
In your case, both modules aspectjrt and org.aspectj.weaver are offering the same package org.aspectj.internal.lang.reflect and that's where the error message comes from (the unnamed module reads package org.aspectj.internal.lang.reflect from both aspectjrt and org.aspectj.weaver).
how do I fix the problem with my project which depends on my two libs?
like Andy Guibert wrote to this topic, you could:
unsplit the package
bundle them in a single package
hope that third party modules become named modules in the future.
AspectJ has been ported to the module system. Check the newest version, if you don't use it (requires org.aspectj.runtime, requires org.aspectj.weaver)?
Additionally, here you can find some more information about the module system.
I just started to have a look at the Java 9 module system and I was wondering whether it is possible for a class to know in which module it is located.
Therefor I created the following module
module de.test {
exports de.test.myexport;
}
and compiled a jar file that looks like
> jar --print-module-descriptor --file=Java9Test-1.0-SNAPSHOT.jar
de.test
requires mandated java.base
exports de.test.myexport
In package de.test, I have a class called Overview where I'm calling
Module module = Overview.class.getModule();
However, the returned module object is unnamed and has no ModuleDescriptor.
Am I using getModule() correctly here, or is there any other way to load the module of a class?
I'm using JDK 9 build 120 on OS X.
All JARs on the class path (with java --class-path ...) get bundled into the same so-called unnamed module, regardless of whether they are "a real module" or "just a JAR". When you ask a class from such a JAR for its module, you get the result you describe.
Try putting the JAR on the module path (with java --module-path ...) and Class::getModule should return what you expect.