1

Please forgive me in advance as I've been using Java since the early 2000s and have been slow to transition new projects toward being compliant with Project Jigsaw and modules (introduced in Java 9.) I'm stuck and hoping someone can help me out. I've tried to create as minimal project as possible to help me focus on the problem. I'm using:

  • JavaFX - I followed the instructions on https://openjfx.io/openjfx-docs/ using their guidance for Modular Gradle with IntelliJ, though I'm not interested in building an image yet, so I'm leaving jlink out of it. This worked just fine.
  • Tablesaw for some pandas-like data crunching
  • JUnit 5.8.2

I have only one class file, HelloFX down the package org.hello.

Executing..

$ .\gradlew run

I get a ResolutionException error from Gradle while trying to run the project:

Error occurred during initialization of boot layer java.lang.module.ResolutionException: Modules shims and RoaringBitmap export package org.roaringbitmap to module listenablefuture

My project tree (all located in a root folder called TestProject):

./gradle
./gradlew
./build.gradle
./.gradle
./gradlew.bat
./settings.gradle
./.idea
./src
./src/test
./src/test/resources
./src/test/java
./src/main
./src/main/resources
./src/main/java
./src/main/java/module-info.java
./src/main/java/org
./src/main/java/org/hello
./src/main/java/org/hello/HelloTS.java

Here are the pertinent files:

settings.gradle

rootProject.name = 'TestProject'

build.gradle

plugins {
    id 'application'
    id 'java'
    id 'idea'
    id 'org.openjfx.javafxplugin' version '0.0.12'
    id 'org.javamodularity.moduleplugin' version '1.8.10'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

javafx {
    version = "17.0.2"
    modules = [ 'javafx.controls', 'javafx.fxml' ]
}

test {
    useJUnitPlatform()
}

dependencies {
    implementation 'tech.tablesaw:tablesaw-core:0.42.0'
    testImplementation 'org.junit.jupiter:junit-jupiter:5.8.2'
}

application {
    mainModule = "$moduleName"
    mainClassName = "org.hello.HelloFX"
}

module-info.java

module TestProject {
    requires javafx.graphics;
    requires javafx.controls;
    requires tablesaw.core;

    exports org.hello;
}

What I've discovered so far:

  • Eliminate Tablesaw - Comment out requires tablesaw.core; from module-info.java and implementation 'tech.tablesaw:tablesaw-core:0.42.0' from build.gradle and my little JavaFX app works just fine with modules, but then I lose Tablesaw.
  • Eliminate modules - Remove module-info.java, then comment out the mainModule line in build.gradle. Then, I can run both a sample JavaFX program and a sample Tablesaw program by simply changing mainClassName to the program I want to run. I can even add some Tablesaw code in my sample JavaFX app, and it works. This is my backup plan, since it gives me what I want, albiet without modularization.

So, I'm really stumped here. This post didn't help, nor did any other that tried to address this weird ResolutionException error from Gradle. My guess is that Tablesaw is not module compliant? Or I need some sort of exclusion clause in my dependencies for Tablesaw? I tried to use the java-library plugin and use the api clause in build.gradle for Tablesaw as it seemed like that plugin is for non-modular libraries, but that didn't work.

There must be a way to do this, but admittedly I am about ready to throw in the towel and, yet again, just go back to non-modular development for my latest project. I have been a huge fan of Java since its inception, (even fully certified back in the Sun Microsystems days! That'll date me!) I understand why modularization has been introduced. Makes complete sense! But frankly, I'm finding its implementation to be quite challenging to embrace.

Any help would be greatly appreciated. Thank you kindly!

Brian King
  • 71
  • 1
  • 6

1 Answers1

1

Tablesaw 0.42.0 isn’t built to support the Java module system.

  1. It has no module-info.
  2. It uses shading for its dependencies
  3. It uses dependencies like RoaringBitmap that have issues if you try to use them with the module system.

I suggest you log an issue with Tablesaw requesting that they modularize the library.

In the meantime, JavaFX should be run from the module path as it is only supported that way, but it will probably be better to run Tablesaw from the class path.

You can put JavaFX on the module path and add the JavaFX modules via command line switches.

Put Tablesaw on the class path, don’t add it as a module.

Don’t define a module-info for your app, create a non-modular app that adds the JavaFX modules via switches. This means that your app code is also on the class path so it can access Tablesaw and it can also access JavaFX modules through virtue of the command line switches.

I don’t use Gradle, so I can’t provide you the exact build script you need for this.

For more info see:

You will probably be able to package your app using the:

jewelsea
  • 150,031
  • 14
  • 366
  • 406
  • Thank you @jewelsea! I ended up resorting to eliminating module-info.java and switching back to a non-modular project. Everything works fine. It's a solution for the short term, but hoping Tablesaw updates its libraries to be module compliant. Thanks again. – Brian King Mar 02 '22 at 14:10
  • 1
    “but hoping Tablesaw updates its libraries to be module compliant” -> as noted in the answer, it is advised that you [create a request for this](https://github.com/jtablesaw/tablesaw/issues). You can link to this question in your request and edit the question or provide a comment to link to the request. – jewelsea Mar 02 '22 at 17:21
  • Done. I just submitted the issue. Thanks again for your help. Much appreciated. – Brian King Mar 03 '22 at 17:04
  • I can imagine Tablesaw eliminating the shade plugin, but if RoaringBitmaps doesn't work with modules, I'm not sure that can be fixed. It is quite central to the implementation. It might be possible to replace it with another bitmap implementation, but the implications for memory usage and performance would need to be understood. – L. Blanc Mar 26 '22 at 23:32
  • I have begun trying to bring tablesaw into the modular future. @jewelsea, you wrote "It uses dependencies like RoaringBitmap that have issues if you try to use them with the module system." How can one tell which libraries have issues with the module system? – L. Blanc Mar 29 '22 at 16:48
  • @L.Blanc this might be a good question to ask as a question (may be duplicate, but I don't know). There are multiple problems which could occur. Easiest to check is to see if it has module-info.java. If it does, it is already built as a proper (non-automatic) module. If it doesn't it can be used as an automatic module but that has limitations. There are various modularity migration guides (of varying quality and completeness) on the net, one is [a guide to module migration pitfalls](https://www.romexsoft.com/blog/migrate-to-java-9/). – jewelsea Mar 30 '22 at 06:40