Reputation: 5272
I've developed a library which module-info.java
looks like that:
module foo.bar {
requires org.apache.commons.lang3;
requires javafx.base;
requires java.validation;
exports foo.bar;
}
This library is used in another project where the module-info.java
contains the following:
module other.project {
requires org.apache.commons.lang3;
requires javafx.base;
requires javafx.graphics;
requires javafx.fxml;
requires foo.bar;
}
When I try to use import javafx.beans.value.WritableValue;
I get the error
Package
javafx.beans.value
is declared infoo.bar
, which does not export it to moduleother.project
.
UPDATE: I created two example projects which reproduce the problem. Please find them here to download.
I do not understand why that is and yet I could not find a solution.
Upvotes: 2
Views: 902
Reputation: 45476
Based on the project posted here, the error that you get when you open the project is:
Package 'javafx.beans.property' is declared in module 'com.example.external.lib', which does not export it to module 'example.project'
The reason for this error is that you are adding some packages from javafx.base
to your external library, but those are not exported to the project that uses this library. The javafx.beans.property
package is internally used by the external module, but it can't be exported.
So these are some proposed changes to make it work.
If you are creating a modular jar (using a module-info
class) as a dependency for another project, you don't need to use the shadow plugin, and you don't need to bundle the JavaFX dependencies in your jars.
So you can have the same module-info.java
file:
module com.example.external.lib {
requires javafx.base;
requires org.apache.commons.lang3;
exports com.example.external.library;
}
with a build.gradle
like this:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.google.gradle:osdetector-gradle-plugin:1.6.0'
}
}
apply plugin: 'com.google.osdetector'
apply plugin: 'java'
ext.platform = osdetector.os == 'osx' ? 'mac' : osdetector.os == 'windows' ? 'win' : osdetector.os
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
repositories {
mavenCentral()
}
dependencies {
compile 'org.apache.commons:commons-lang3:3.8.1'
compile "org.openjfx:javafx-base:11:$platform"
}
compileJava {
doFirst {
options.compilerArgs = [
'--module-path', classpath.asPath,
'--add-modules', 'javafx.base'
]
}
}
Now, when you run gradle build
, you will generate libs/external-library.jar
, a 2 KB jar, without JavaFX dependencies.
Note that if you still want to do shadow jar with this external project, you can use compileOnly "org.openjfx:javafx-base:11:$platform"
to keep the JavaFX dependencies out of this jar.
You can add that jar to the project.
build.gradle
:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.google.gradle:osdetector-gradle-plugin:1.6.0'
}
}
apply plugin: 'com.google.osdetector'
apply plugin: 'java'
ext.platform = osdetector.os == 'osx' ? 'mac' : osdetector.os == 'windows' ? 'win' : osdetector.os
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
repositories {
mavenCentral()
}
dependencies {
compile files('libs/external-library.jar')
compile 'org.apache.commons:commons-lang3:3.8.1'
compile "org.openjfx:javafx-base:11:$platform"
}
compileJava {
doFirst {
options.compilerArgs = [
'--module-path', classpath.asPath,
'--add-modules', 'javafx.base'
]
}
}
But now your module-info
file should include again the javafx.base
dependency:
module example.project {
requires javafx.base;
requires com.example.external.lib;
exports com.example.project;
}
You can run gradle build
to generate a jar, and IntelliJ won't complain anymore.
If you want to have a shadow jar at the end, you can also apply:
buildscript {
repositories {
mavenCentral()
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath 'com.google.gradle:osdetector-gradle-plugin:1.6.0'
}
}
apply plugin: 'application'
apply plugin: 'com.google.osdetector'
ext.platform = osdetector.os == 'osx' ? 'mac' : osdetector.os == 'windows' ? 'win' : osdetector.os
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
repositories {
mavenCentral()
}
dependencies {
compile files('libs/external-library.jar')
compile 'org.apache.commons:commons-lang3:3.8.1'
compile "org.openjfx:javafx-base:11:$platform"
}
compileJava {
doFirst {
options.compilerArgs = [
'--module-path', classpath.asPath,
'--add-modules', 'javafx.base'
]
}
}
run {
doFirst {
jvmArgs = [
'--module-path', classpath.asPath,
'--add-modules', 'javafx.base'
]
}
}
mainClassName = "com.example.project.PublicClass"
jar {
manifest {
attributes 'Main-Class': 'com.example.project.PublicClass'
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
so you would be able to run java -jar build/libs/project-using-external-lib.jar
. Note that this jar will contain the JavaFX classes.
Doing a shadow jar is not to the recommended way to distribute your project, but since you have automatic modules (commons-lang3) you can't use jlink
, unless you convert that into an explicit module (see this answer).
Upvotes: 2