1

I'm using the Oracle “Self-Contained Application Packaging” tool to make a .deb file for a JavaFX 8 desktop application. The generated package file can be installed without problems on Ubuntu but then the application fails to run. The file is installed as follows:

$ sudo dpkg -i vocabhunter-1.0.14.deb

However, attempting to run the application generates the following error:

$ /opt/VocabHunter/VocabHunter
VocabHunter Failed to locate JNI_CreateJavaVM
VocabHunter Failed to launch JVM

Importantly, I'm generating a bundle without the JRE included and on investigation it seems that the problem relates to this. The generated file /opt/VocabHunter/app/VocabHunter.cfg contains the following line:

app.runtime=

If I edit this and add the path to Java, the program launches without problems. As a workaround, I've suggested that after installing the .deb bundle the user run the following command:

sudo sed -i "s|app.runtime=.*|app.runtime=$JAVA_HOME|g" /opt/VocabHunter/app/VocabHunter.cfg

However, this makes things hard for the user. Does anyone know how to fix the configuration for the JavaFX packaging tool to avoid this problem?

The build uses Gradle to call an Ant script to generate the bundle. Gradle fills in all of the necessary variables. The Ant script is as follows:

<project name="VocabHunter Packaging" basedir=""
         xmlns:fx="javafx:com.sun.javafx.tools.ant">
    <property environment="env"/>
    <property name="JAVA_HOME" value="${env.JAVA_HOME}"/>
    <target name="jfxbundle" description="Build the application bundle">
        <taskdef resource="com/sun/javafx/tools/ant/antlib.xml"
                 uri="javafx:com.sun.javafx.tools.ant"
                 classpath="${JAVA_HOME}/lib/ant-javafx.jar"/>
        <fx:deploy outdir="${basedir}/build"
                   nativeBundles="${packageType}">
            <fx:platform basedir=""/>
            <fx:application id="VocabHunterId"
                            name="VocabHunter"
                            mainClass="${mainClass}"
                            version="${version}"/>
            <fx:resources>
                <fx:fileset dir="${basedir}/build/libs"/>
            </fx:resources>
            <fx:info title="VocabHunter">
                <fx:association description="VocabHunter session"
                                extension="wordy"
                                mimetype="application/x-vnd.VocabHunterSession"
                                icon="${sessionIcon}"/>
            </fx:info>
            <fx:bundleArgument arg="icon"
                               value="${appIcon}"/>
            <fx:bundleArgument arg="mac.CFBundleVersion"
                               value="${version}"/>
            <fx:bundleArgument arg="launcher-cfg-format"
                               value="prop"/>
        </fx:deploy>
    </target>
</project>

You can see the full script in context here.

I'm testing this using JDK 1.8.0_92 on Ubuntu 14.04.

Adam
  • 682
  • 1
  • 6
  • 27
  • 1
    This may be the same thing as in [my question](http://stackoverflow.com/questions/32795309/linux-executable-fails-using-javafx-maven-plugin). Also take a look at the two bug reports https://bugs.openjdk.java.net/browse/JDK-8143314 and https://bugs.openjdk.java.net/browse/JDK-8143934. The latter on should be solved with 8u76. – hotzst Mar 06 '16 at 12:51
  • Hi @hotzst. Thanks for the link to the question. Certainly it looks related as the error messages are similar. I'm not clear after reading your answer what you did to solve the problem though. Can you suggest how I might apply what you did to solve this problem? – Adam Mar 08 '16 at 15:07
  • First step is to determine if the issue is with the executable jar or the launcher. To do that execute the jar file with `java -jar ...`. If it is the launcher it might be related to the configuration. In my case the the cfg file could not be resolved as it is calculated from the application name, which contains a `.`. Linux executable do not require a specific file suffix to be executable, Windows does. – hotzst Mar 08 '16 at 15:47
  • It seems unlikely to be a problem with the executable jar as editing the `.cfg` file using the `sed` command (see above) enables the program to run. Any ideas how to fix the config? – Adam Mar 08 '16 at 16:14
  • The maven plugin has a workaround for [this issue](https://github.com/javafx-maven-plugin/javafx-maven-plugin/issues/167), so you could consider building with Maven instead of Ant, or figure out what they did and then apply the same approach. – hotzst Mar 09 '16 at 13:46
  • The workaround from the issue you mention is to add ``. I added this a while back to fix a problem with the Mac `DMG` bundle (see http://stackoverflow.com/questions/33898461). Unfortunately this doesn't fix the problem with the Linux `DEB` bundle. – Adam Mar 11 '16 at 08:31

1 Answers1

2

To answer this here too, you are required to have JRE_HOME being set for running some native JavaFX launcher without having bundled JRE. On Windows it looks inside the registry and searches for HKLM\Software\JavaSoft\Java Runtime Environment\[CurrentVersion]\JavaHome. I could NOT find any documentation about this.

To workaround this, you are required to "update" the app.runtime-value as part of the postinst-script being executed while installing. Something like this:

#!/bin/sh
# postinst script for APPLICATION_NAME
#
# see: dh_installdeb(1)

set -e

# summary of how this script can be called:
#        * <postinst> `configure' <most-recently-configured-version>
#        * <old-postinst> `abort-upgrade' <new version>
#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>
#          <new-version>
#        * <postinst> `abort-remove'
#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
#          <failed-install-package> <version> `removing'
#          <conflicting-package> <version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package

case "$1" in
    configure)
        echo Adding shortcut to the menu
SECONDARY_LAUNCHERS_INSTALL
APP_CDS_CACHE
        xdg-desktop-menu install --novendor /opt/APPLICATION_FS_NAME/APPLICATION_LAUNCHER_FILENAME.desktop
FILE_ASSOCIATION_INSTALL

        if [ "SERVICE_HINT" = "true" ]; then
            echo Installing daemon
            cp /opt/APPLICATION_FS_NAME/APPLICATION_PACKAGE.init /etc/init.d/APPLICATION_PACKAGE

            if [ -x "/etc/init.d/APPLICATION_PACKAGE" ]; then
                update-rc.d APPLICATION_PACKAGE defaults

                if [ "START_ON_INSTALL" = "true" ]; then
                    if which invoke-rc.d >/dev/null 2>&1; then
                        invoke-rc.d APPLICATION_PACKAGE start
                    else
                        /etc/init.d/APPLICATION_PACKAGE start
                    fi
                fi
            fi

        fi

        if [ -f /etc/profile ]; then
            # load special environment variables
            . /etc/profile

            # remove stored value in case of dpkg-reconfigure
            RUNTIME_PATH_TO_SET=""

            if [ -z "$JRE_HOME" ]; then
                echo JRE_HOME is not set, checking for JAVA_HOME being set
                if [ -z "$JAVA_HOME" ]; then
                    echo JAVA_HOME is not set, checking for known locations

                    # look for known locations
                    KNOWN_JDK_DIRS="/usr/lib/jvm/java-8-oracle /usr/lib/jvm/java-8-openjdk-amd64 /usr/lib/jvm/java-8-openjdk-i386"
                    FOUND_JAVA_HOME=""

                    # Look for the right JVM to use (use the first one)
                    for potentialjdkdir in $KNOWN_JDK_DIRS; do
                        if [ -r "$potentialjdkdir/bin/java" -a -z "$FOUND_JAVA_HOME" ]; then
                            FOUND_JAVA_HOME="$potentialjdkdir"
                        fi
                    done

                    if [ -z "$FOUND_JAVA_HOME" ]; then
                        # still nothing found :(
                        echo Please make sure to have Java installed and JRE_HOME variable set before running APPLICATION_LAUNCHER_FILENAME
                    else
                        echo Updating runtime-settings using known location
                        RUNTIME_PATH_TO_SET="$FOUND_JAVA_HOME"
                    fi
                else
                    echo Updating runtime-settings using JAVA_HOME
                    # JAVA_HOME is set, use that value
                    RUNTIME_PATH_TO_SET="$JAVA_HOME"
                fi
            fi

            # always write runtime-location, as it might get removed again when user calls dpkg-reconfigure
            sed -i "s|app.runtime=.*|app.runtime=$RUNTIME_PATH_TO_SET|g" /opt/APPLICATION_FS_NAME/app/APPLICATION_LAUNCHER_FILENAME.cfg
        fi
    ;;

    abort-upgrade|abort-remove|abort-deconfigure)
    ;;

    *)
        echo "postinst called with unknown argument \`$1'" >&2
        exit 1
    ;;
esac

# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.

#DEBHELPER#

exit 0

When using the javafx-maven-plugin or javafx-gradle-plugin, put this script inside src/main/deploy/package/linux with the filename postinst to get picked up by the javapackager/bundler.

Disclaimer: I'm the maintainer of the javafx-maven-plugin and creator of the javafx-gradle-plugin

EDIT: updated script for working on dpkg-reconfigure too

FibreFoX
  • 2,858
  • 1
  • 19
  • 41