javafxioexceptionjpackage

Jpackage - Accessing resources bundled with package


I'm packaging my JavaFX project as installer using JPackageScriptFX, and I've created a folder called "resources" which is present at the basedir of my source package. I've included this folder in my package by passing --app-content resources flag:

$JAVA_HOME/bin/jpackage \
--type $INSTALLER_TYPE \
--dest target/installer \
--input target/libs \
--app-content resources \
--name "$NAME" \
--vendor "$VENDOR" \
--main-class ${MAIN_CLASS}.AppLauncher \
--main-jar ${MAIN_JAR} \
--java-options -Xmx2048m \
--runtime-image target/java-runtime \
--icon ${ICON} \
--app-version ${APP_VERSION} \

This is my source code folders directory structure:

Project
|
|-resources
|         |-icon.png
|
|-src
|
|-pom.xml
.
.
.

After the package is created and installed successfully, the installation directory's structure is:

Project
|
|-bin
|   |-project
|
|-lib
|   |-app
|   |   |-project.jar
|   |   |-project.cfg
|   |
|   |-resources
|   |         |-icon.png
|   |
|   |-runtime
|
|-share

When I'm running the project, I'm getting the FileNotFoundException on method: DBIO.loadResource

public class DBIO {
    private DBIO(){/*NOTHING*/}
    private static InputStream loadResource(String path){
        try{
            return new FileInputStream("resources/"+path);
        }catch(IOException ex){
            ex.printStackTrace();
        }
        return null;
    }
    public static final Image LOGO = new Image(loadResource("icon.png"));
}
java.io.FileNotFoundException: resources/icon.png (No such file or directory)
    at java.base/java.io.FileInputStream.open0(Native Method)
    at java.base/java.io.FileInputStream.open(Unknown Source)
    at java.base/java.io.FileInputStream.<init>(Unknown Source)
    at java.base/java.io.FileInputStream.<init>(Unknown Source)
    at project.app.DBIO.loadResource(DBIO.java:24)
    at project.app.DBIO.<clinit>(DBIO.java:30)
    at project.app.EULAController.<clinit>(EULAController.java:29)
    at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized0(Native Method)
    at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized(Unknown Source)
    at java.base/jdk.internal.reflect.MethodHandleAccessorFactory.ensureClassInitialized(Unknown Source)
    at java.base/jdk.internal.reflect.MethodHandleAccessorFactory.newConstructorAccessor(Unknown Source)
    at java.base/jdk.internal.reflect.ReflectionFactory.newConstructorAccessor(Unknown Source)
    at java.base/java.lang.reflect.Constructor.acquireConstructorAccessor(Unknown Source)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Unknown Source)
    at java.base/java.lang.reflect.Constructor.newInstance(Unknown Source)
    at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:941)
    at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:983)
    at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:230)
    at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:757)
    at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2853)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2649)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2563)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2531)
    at project.app.App.start(App.java:16)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:839)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:483)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:456)
    at java.base/java.security.AccessController.doPrivileged(Unknown Source)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:455)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
    at com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$10(GtkApplication.java:263)
    at java.base/java.lang.Thread.run(Unknown Source)

Exception in Application start method
Exception in thread "main" java.lang.RuntimeException: Exception in Application start method
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:893)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:196)
    at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ExceptionInInitializerError
    at project.app.EULAController.<clinit>(EULAController.java:29)
    at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized0(Native Method)
    at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized(Unknown Source)
    at java.base/jdk.internal.reflect.MethodHandleAccessorFactory.ensureClassInitialized(Unknown Source)
    at java.base/jdk.internal.reflect.MethodHandleAccessorFactory.newConstructorAccessor(Unknown Source)
    at java.base/jdk.internal.reflect.ReflectionFactory.newConstructorAccessor(Unknown Source)
    at java.base/java.lang.reflect.Constructor.acquireConstructorAccessor(Unknown Source)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Unknown Source)
    at java.base/java.lang.reflect.Constructor.newInstance(Unknown Source)
    at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:941)
    at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:983)
    at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:230)
    at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:757)
    at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2853)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2649)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2563)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2531)
    at project.app.App.start(App.java:16)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:839)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:483)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:456)
    at java.base/java.security.AccessController.doPrivileged(Unknown Source)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:455)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
    at com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$10(GtkApplication.java:263)
    ... 1 more
Caused by: java.lang.NullPointerException: Cannot invoke "java.io.File.toPath()" because "file" is null
    at project.app.DBIO.writeToFile(DBIO.java:73)
    at project.app.Util.log(Util.java:43)
    at project.app.DBIO.loadResource(DBIO.java:26)
    at project.app.DBIO.<clinit>(DBIO.java:30)
    ... 27 more

EDIT: If I copy the resources folder inside Project/bin the project starts working. That means the program is looking for resources folder inside bin. How should I point it to look in the correct location (inside /lib)?


Solution

  • resources folder can be included into a project through jpackage using

    --app-content resources

    This folder will be present as Project/lib/resources in Linux and Project\resources in Windows.

    Access to this folder can be made through:

    String resourcesDir = new File(getClass().getProtectionDomain().getCodeSource()
    .getLocation().getPath()).getParentFile().getParent()+"/resources/";
    

    Points to notice