1

I am migrating my javafx application to use Java Modules (JPMS). Everything works fine except loading resources. This question or this didn't help.

The kotlin code that tries to load a resource in class Main.kt:

javaClass.getResource("/fxml/scene-splash.fxml") // returns null

This is the directory structure:

 src
  └───  main
      ├───  kotlin
      │   ├───  com
      │   │   └───  pleon
      │   │       └───  donim
      │   │           ├───  controller
      │   │           └─── Main.kt
      │   └─── module-info.java
      └───  resources
          ├───  img
          ├───  fxml
          │   └─── scene-splash.fxml
          └───  META-INF
              └─── MANIFEST.MF

and this is the module-info.java:

module donim.application {
    requires java.base;
    requires java.desktop;
    requires kotlin.stdlib;

    requires javafx.base;
    requires javafx.graphics;
    requires javafx.controls;
    requires javafx.media;
    requires javafx.fxml;

    // The com.jhlabs:filters library
    requires filters;

    exports com.pleon.donim;
    exports com.pleon.donim.node;
    opens com.pleon.donim.controller;
}

and this is the full java command executed by IntelliJ:

"C:\Program Files\Java\jdk-15\bin\java.exe"
--add-modules javafx.base,javafx.graphics
--add-reads javafx.base=ALL-UNNAMED
--add-reads javafx.graphics=ALL-UNNAMED
"-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2020.2\lib\idea_rt.jar=3702:C:\Program Files\JetBrains\IntelliJ IDEA 2020.2\bin"
-Dfile.encoding=UTF-8
-p
 D:\IdeaProjects\donim\out\production\classes;
 D:\IdeaProjects\donim\out\production\resources;
 C:\Users\ABC\.gradle\caches\modules-2\files-2.1\org.openjfx\javafx-base\15\df61e6a8cfba8e36f598e3fa4d40fd51561efdf8\javafx-base-15-win.jar;
 C:\Users\ABC\.gradle\caches\modules-2\files-2.1\org.openjfx\javafx-graphics\15\979ac3da4288de1e8103c2b38eb7aa74d32fe1b8\javafx-graphics-15-win.jar;
 C:\Users\ABC\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-jdk8\1.4.10\998caa30623f73223194a8b657abd2baec4880ea\kotlin-stdlib-jdk8-1.4.10.jar;
 C:\Users\ABC\.gradle\caches\modules-2\files-2.1\org.openjfx\javafx-fxml\15\a5a853b7f1f821c98bc49819dbe6c3792e4f3e1a\javafx-fxml-15-win.jar;
 C:\Users\ABC\.gradle\caches\modules-2\files-2.1\org.openjfx\javafx-controls\15\c2fffd91566c6c26bf0cb6c514be271b897f0254\javafx-controls-15.jar;
 C:\Users\ABC\.gradle\caches\modules-2\files-2.1\org.openjfx\javafx-controls\15\9424a90300b37786c9072f08d7a791fa9b6be13e\javafx-controls-15-win.jar;
 C:\Users\ABC\.gradle\caches\modules-2\files-2.1\org.openjfx\javafx-media\15\b53695aa0c89e910ac27fbb685c0a6066dac590e\javafx-media-15-win.jar;
 C:\Users\ABC\.gradle\caches\modules-2\files-2.1\org.openjfx\javafx-graphics\15\2a472aea82dc19b0f3b5b349277e6520b39c4b9\javafx-graphics-15.jar;
 C:\Users\ABC\.gradle\caches\modules-2\files-2.1\org.openjfx\javafx-base\15\c6db58e57b76f797f6b1abf763e173f0d1b9b810\javafx-base-15.jar;
 C:\Users\ABC\.gradle\caches\modules-2\files-2.1\com.jhlabs\filters\2.0.235-1\fff65ebe39d1097cee431087858b3caf957ecfb7\filters-2.0.235-1.jar;
 C:\Users\ABC\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-jdk7\1.4.10\30e46450b0bb3dbf43898d2f461be4a942784780\kotlin-stdlib-jdk7-1.4.10.jar;
 C:\Users\ABC\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib\1.4.10\ea29e063d2bbe695be13e9d044dcfb0c7add398e\kotlin-stdlib-1.4.10.jar;
 C:\Users\ABC\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-common\1.4.10\6229be3465805c99db1142ad75e6c6ddeac0b04c\kotlin-stdlib-common-1.4.10.jar;
 C:\Users\ABC\.gradle\caches\modules-2\files-2.1\org.jetbrains\annotations\13.0\919f0dfe192fb4e063e7dacadee7f8bb9a2672a9\annotations-13.0.jar
-m donim.application/com.pleon.donim.Main

My current workaround is to add the path of resources as classpath in IntelliJ jvm arguments like this:

--class-path out/production/resources

Here is my full source code.

Mahozad
  • 18,032
  • 13
  • 118
  • 133
  • Check the contents of the build (`out` folder or jar file) to make sure the resources are being deployed where you think. – James_D Sep 19 '20 at 16:54
  • Copy of all resources is available in `out/production/resources/` – Mahozad Sep 19 '20 at 17:00
  • The answer for this question (asked yesterday) https://stackoverflow.com/questions/63950805/where-are-fxml-files-in-maven-project-with-javafx-dependency/63964488#63964488 makes it clear where your sources and resources have to be placed. – mipa Sep 19 '20 at 17:20
  • @mipa As I said in question body, It didn't work for me. – Mahozad Sep 19 '20 at 17:24
  • The answer to https://stackoverflow.com/questions/61531317/how-do-i-determine-the-correct-path-for-fxml-files-css-files-images-and-other gives a very detailed look at how to locate .fxml files. – Some Guy Dec 31 '22 at 14:30

2 Answers2

0

In modules resources are only available through the opens clause,

From JDK 12, resource directories are also considered packages, so looking that you are using JDK 15 - What you want is kotlin.stdb to opens its resource for access

Hard to tell which library has the /fxml but something close to this

--add-opens=javafx.fxml/fmx=kotlin.stdb

This will be required until Kotlin either declares module-files with open clauses for their resource packages, or modified by command line execution.

Marc Magon
  • 713
  • 7
  • 11
  • Is `b` a typo in kotlin.std`b`lib? What is the `fmx` package? When I try `--add-opens=kotlin.stdlib/fmx=donim.application` I get this: `WARNING: package fmx not in kotlin.stdlib` – Mahozad Oct 22 '20 at 08:40
  • probably a typo - :) - Also, the module location of the FMX package, that is what should open to kotlin, I don't have the source artefacts so I can't really pinpoint which module must open the package – Marc Magon Oct 22 '20 at 10:01
  • Looking a bit more, it could be javafx.fxml/fxml=kotlin.stdlib - kotlin library needs open access to the fxml package :) – Marc Magon Oct 22 '20 at 10:03
  • There is no `fmx` or `fxml` package in javafx.fxml. I think it's `javafx.fxml` package instead. Tried `--add-opens=javafx.fxml/javafx.fxml=kotlin.stdlib` but the resources still cannot be loaded. – Mahozad Oct 22 '20 at 10:20
  • Hmm there is definitely a module with the package /fmxl, what you've done there is declare the module twice, You have the right idea, it's identifying which module has the package (that contains that resource) and then opening it :) – Marc Magon Oct 23 '20 at 10:31
-1

i think it's supposed to work like so:
suppose you've got the folder like

  resources
 ├───  img
 ├───  fxml
 |   ├─── scene-splash_controller.java
 │   └─── scene-splash.fxml
 └───  META-INF
     └─── MANIFEST.MF

then you should do
scene-splash_controller.getResource("/fxml/scene-splash.fxml");
i will put you an example that works on my pc

(it's in the MainApp class)

    FXMLLoader loader = new FXMLLoader();
    loader.setLocation(MainApp.class.getResource("./StartMenuLayout.fxml"));
    GridPane gp=(GridPane) loader.load();

    //link the fxml controller with MainApp
    StartPage startP=loader.getController();
    startP.setMainApp(this);

more in depth explanation there https://stackoverflow.com/a/61531318/12424449

safir
  • 84
  • 6
  • No, a java file does not belong into the resources folder. Instead you should move the fxml into the same package as the controller and then remove the /fxml/ in front of the resource path. – mipa Sep 19 '20 at 17:12