SETUP:
I'm using the Modular with Gradle option from the official OpenJFX documentation.
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 myURL. - 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
srcfolder as seen in the image above (since he mentions IDE). - The
src/mainfolder since that's where all the "source" code is (i.e.javafolder with the package and.javafiles). - The "main" folder which contains all of folders and resources once the application is built (as seen by the
jimage list modulescommand). - 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
