3

SETUP:

I'm using the Modular with Gradle option from the official OpenJFX documentation.

File Structure:

File Structure

As suggested in here, I tried using this for all of my resources:

URL cssURL = getClass().getResource("/org/jamesd/examples/css/style.css"); scene.getStylesheets().add(cssURL.toExternalForm());

So, in my case, in order to load my main .fxml file (and all resources), it would be:

URL urlFXML = getClass().getResource("/fxml/file.fxml");
Parent root = FXMLLoader.load(urlFXML);

PROBLEM:

When I click on Run -> Run Main.java (with the code set up as above), I get the infamous java.lang.NullPointerException: Location is required., but when I build the application using jlink, it works - as it should!

As suggested in this topic, I used the jimage list modules command and it gave me the following structure:

Module: [module]
    META-INF/MANIFEST.MF
    [com]/[company]/[package]/Main.class
    [com]/[company]/[package]/controllers/[Controller].class
    fxml/file.fxml
    img/logo.png
    module-info.class
    style/style.css

In order for me to be able to run the application without building it everytime, I have to set my resource URLs like so:

URL urlFXML = new File("src/main/resources/fxml/file.fxml").toURI().toURL();
Parent root = FXMLLoader.load(urlFXML);

If I do that, though, after building my application with jlink, I get this error:

java.io.FileNotFoundException: /home/[user]/Documents/Projects/[folder]/[folder]/[folder]/[projectname]/build/image/bin/src/main/resources/fxml/file.fxml (No such file or directory)

Which makes sense, as you can see from the jimage list modules command from above.

I can't figure out what's messing with me, the IDE, Gradle, jlink or my incompetence.

I also made sure that I've covered the "Troubleshooting" section (from the second link) as well:

  • I'm using valid names for my resources.
  • Since I'm using getClass().getResource(), I'm using / in my URL.
  • In this last point, which is:

Remember that absolute paths are defined relative to the classpath. Typically the root of the classpath is the union of all source and resource folders in your IDE.

I'm not sure which of these the author means:

  • The src folder as seen in the image above (since he mentions IDE).
  • The src/main folder since that's where all the "source" code is (i.e. java folder with the package and .java files).
  • The "main" folder which contains all of folders and resources once the application is built (as seen by the jimage list modules command).
  • Or the directory of files that I get after running this code (ran by Run -> Main.java in the IDE, not after building the application):

File file = new File(".");

System.out.print("Files: \n");

for(String fileNames : file.list()) System.out.println(fileNames);

Which returns:

Files: 
gradle
settings.gradle
.idea
src
build
build.gradle
gradlew.bat
gradlew
.gradle

I also tried adding the following code to my build.gradle file, but it didn't seem to do anything:

sourceSets {
    main {
        resources {
            srcDirs = ["src/main/resources"]
            includes = ["**/*.fxml"]
        }
    }
}

Question:

Is there a way to set up the resource URLs which works for both when I run the application and build it while maintaining my current file structure?

Source/Demo (GitHub won't let me upload it - too big when compressed or too many files/folders - sorry for the inconvenience).

I've included a built jlink image, which only needs to be run. If you want to test it using absolute paths, uncomment the URLs in Main.java.

Edit 1:

Directory tree of the build folder:

.
├── classes
│   └── java
│       └── main
│           ├── com
│           │   └── company
│           │       └── app
│           │           ├── controllers
│           │           │   └── TestingController.class
│           │           └── Main.class
│           └── module-info.class
├── generated
│   └── sources
│       ├── annotationProcessor
│       │   └── java
│       │       └── main
│       └── headers
│           └── java
│               └── main
├── image
│   ├── bin
│   │   ├── app
│   │   ├── app.bat
│   │   ├── java
│   │   ├── jrunscript
│   │   └── keytool
│   ├── conf
│   │   ├── net.properties
│   │   ├── sdp
│   │   │   └── sdp.conf.template
│   │   ├── security
│   │   │   ├── java.policy
│   │   │   ├── java.security
│   │   │   └── policy
│   │   │       ├── limited
│   │   │       │   ├── default_local.policy
│   │   │       │   ├── default_US_export.policy
│   │   │       │   └── exempt_local.policy
│   │   │       ├── README.txt
│   │   │       └── unlimited
│   │   │           ├── default_local.policy
│   │   │           └── default_US_export.policy
│   │   └── sound.properties
│   ├── include
│   │   ├── classfile_constants.h
│   │   ├── jawt.h
│   │   ├── jni.h
│   │   ├── jvmticmlr.h
│   │   ├── jvmti.h
│   │   └── linux
│   │       ├── jawt_md.h
│   │       └── jni_md.h
│   ├── legal
│   │   ├── java.base
│   │   │   ├── ADDITIONAL_LICENSE_INFO
│   │   │   ├── aes.md
│   │   │   ├── asm.md
│   │   │   ├── ASSEMBLY_EXCEPTION
│   │   │   ├── cldr.md
│   │   │   ├── c-libutl.md
│   │   │   ├── icu.md
│   │   │   ├── LICENSE
│   │   │   ├── public_suffix.md
│   │   │   └── unicode.md
│   │   ├── java.datatransfer
│   │   │   ├── ADDITIONAL_LICENSE_INFO -> ../java.base/ADDITIONAL_LICENSE_INFO
│   │   │   ├── ASSEMBLY_EXCEPTION -> ../java.base/ASSEMBLY_EXCEPTION
│   │   │   └── LICENSE -> ../java.base/LICENSE
│   │   ├── java.desktop
│   │   │   ├── ADDITIONAL_LICENSE_INFO -> ../java.base/ADDITIONAL_LICENSE_INFO
│   │   │   ├── ASSEMBLY_EXCEPTION -> ../java.base/ASSEMBLY_EXCEPTION
│   │   │   ├── colorimaging.md
│   │   │   ├── giflib.md
│   │   │   ├── harfbuzz.md
│   │   │   ├── jpeg.md
│   │   │   ├── lcms.md
│   │   │   ├── libpng.md
│   │   │   ├── LICENSE -> ../java.base/LICENSE
│   │   │   ├── mesa3d.md
│   │   │   └── xwd.md
│   │   ├── java.prefs
│   │   │   ├── ADDITIONAL_LICENSE_INFO -> ../java.base/ADDITIONAL_LICENSE_INFO
│   │   │   ├── ASSEMBLY_EXCEPTION -> ../java.base/ASSEMBLY_EXCEPTION
│   │   │   └── LICENSE -> ../java.base/LICENSE
│   │   ├── java.scripting
│   │   │   ├── ADDITIONAL_LICENSE_INFO -> ../java.base/ADDITIONAL_LICENSE_INFO
│   │   │   ├── ASSEMBLY_EXCEPTION -> ../java.base/ASSEMBLY_EXCEPTION
│   │   │   └── LICENSE -> ../java.base/LICENSE
│   │   ├── java.xml
│   │   │   ├── ADDITIONAL_LICENSE_INFO -> ../java.base/ADDITIONAL_LICENSE_INFO
│   │   │   ├── ASSEMBLY_EXCEPTION -> ../java.base/ASSEMBLY_EXCEPTION
│   │   │   ├── bcel.md
│   │   │   ├── dom.md
│   │   │   ├── jcup.md
│   │   │   ├── LICENSE -> ../java.base/LICENSE
│   │   │   ├── xalan.md
│   │   │   └── xerces.md
│   │   └── jdk.unsupported
│   │       ├── ADDITIONAL_LICENSE_INFO -> ../java.base/ADDITIONAL_LICENSE_INFO
│   │       ├── ASSEMBLY_EXCEPTION -> ../java.base/ASSEMBLY_EXCEPTION
│   │       └── LICENSE -> ../java.base/LICENSE
│   ├── lib
│   │   ├── classlist
│   │   ├── jexec
│   │   ├── jrt-fs.jar
│   │   ├── jspawnhelper
│   │   ├── jvm.cfg
│   │   ├── libawt_headless.so
│   │   ├── libawt.so
│   │   ├── libawt_xawt.so
│   │   ├── libfontmanager.so
│   │   ├── libjavajpeg.so
│   │   ├── libjava.so
│   │   ├── libjawt.so
│   │   ├── libjimage.so
│   │   ├── libjli.so
│   │   ├── libjsig.so
│   │   ├── libjsound.so
│   │   ├── liblcms.so
│   │   ├── libmlib_image.so
│   │   ├── libnet.so
│   │   ├── libnio.so
│   │   ├── libprefs.so
│   │   ├── libsplashscreen.so
│   │   ├── libverify.so
│   │   ├── libzip.so
│   │   ├── modules
│   │   ├── psfontj2d.properties
│   │   ├── psfont.properties.ja
│   │   ├── security
│   │   │   ├── blacklisted.certs
│   │   │   ├── cacerts
│   │   │   ├── default.policy
│   │   │   └── public_suffix_list.dat
│   │   ├── server
│   │   │   ├── libjsig.so
│   │   │   └── libjvm.so
│   │   └── tzdb.dat
│   └── release
├── jlinkbase
│   ├── delegating
│   ├── jlinkjars
│   │   ├── javafx-base-11.0.2-linux.jar
│   │   ├── javafx-controls-11.0.2-linux.jar
│   │   ├── javafx-fxml-11.0.2-linux.jar
│   │   ├── javafx-graphics-11.0.2-linux.jar
│   │   ├── testing-1.0.jar
│   │   └── testing.merged.module-1.0.jar
│   ├── mergedjars
│   ├── nonmodjars
│   ├── tmpmerged
│   │   └── testing.merged.module-1.0.jar
│   └── tmpmodinfo
│       └── module-info.class
├── libs
│   └── testing-1.0.jar
├── resources
│   └── main
│       ├── fxml
│       │   └── file.fxml
│       ├── img
│       │   └── logo.png
│       ├── lang
│       ├── lib
│       ├── META-INF
│       │   └── MANIFEST.MF
│       └── style
│           └── style.css
└── tmp
    ├── compileJava
    │   └── source-classes-mapping.txt
    └── jar
        └── MANIFEST.MF
Doombringer
  • 596
  • 4
  • 19
  • Have you tried getClass().getResource("fxml/file.fxml")without the first / ? – Tokazio Feb 21 '21 at 22:29
  • 1
    When running in the IDE, is it running from the file system or from a jar file? Check the content of the build folder or jar file as appropriate, and make sure the resources are being deployed there correctly. – James_D Feb 21 '21 at 22:37
  • @Tokazio I did try it, though, it's actually not correct, because without the `/` it's looking for an `fxml` folder where the `Main.java` is. @James_D Yes, it's running from the system. I also tried synchronizing (File -> Read all from disk option) and invalidating the chaces + restart, they didn't help I'm afraid. – Doombringer Feb 21 '21 at 22:49
  • Check in the build folder or out folder of inteliij if you have your resources in the good folders. With gradle you may handle manually where to put these files... – Tokazio Feb 21 '21 at 22:53
  • @Tokazio Check "Edit 1". – Doombringer Feb 21 '21 at 23:26
  • Intelij seems to have a particular configuration to run javafx, https://www.jetbrains.com/help/idea/javafx.html – Tokazio Feb 21 '21 at 23:49
  • @Tokazio The instructions there are for a non-modular from IDE project. – Doombringer Feb 21 '21 at 23:57
  • 1
    Don't say "Run Main.java" when executing from IntelliJ. Have IntelliJ execute the Gradle `run` task added by the `application` plugin. Make sure you've configured that plugin so Gradle knows which module is your main module and which class is your main class. – Slaw Feb 22 '21 at 00:04
  • @Slaw Well, f*ck me sideways and call me Judy! I did that, got the [javaExecHandleBuilder bug](https://stackoverflow.com/questions/63997525/task-run-causes-org-joor-reflectexception-java-lang-nosuchfieldexception-ja). I did what the link says and now it runs via IntelliJ. I honestly thought doing **Gradle -> Tasks -> Application -> Run** was the same as simply running the `Main.java` file. If you put it in an answer, I'd be more than happy to mark it as a solution, so others can find it more easily. <3 – Doombringer Feb 22 '21 at 00:17

0 Answers0