Distributing JavaFX 11 Application

Nicolas Therrien nicolas.therrien at motorolasolutions.com
Tue Feb 26 01:17:25 UTC 2019


Hi!

Thanks Sverre for your response and help in this matter! I am learning more
about Jpackage. However, the need to build on each OS platform to produce
installers is a drawback from our previous Java 8 packages and I was asked
to find another solution.

The good news is that I have managed to find a way to build multi-platform
Java 11 packages on any OS platform. I wanted to share that knowledge back
with the group.

The project dependencies are set as usual:
    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>11.0.2</version>
        </dependency>

        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
            <version>11.0.2</version>
        </dependency>
    </dependencies>

Then the project uses simple launch scripts like this:
windows:
start javaw -Dfile.encoding=UTF-8 --module-path modules --module
modulename/class.package.Main
linux:
java -Dfile.encoding=UTF-8 --module-path modules --module
modulename/class.package.Main


These commands expect the proper jar files to be in the directory named
"modules".

The project uses Maven's copy dependencies like this:
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy-dependencies</id>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>

<outputDirectory>${project.build.directory}/staging/modules</outputDirectory>
                            <includeScope>runtime</includeScope>

<excludeClassifiers>linux,win</excludeClassifiers>
                        </configuration>
                    </execution>
                    <execution>
                        <id>copy-linux-dependencies</id>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>

<outputDirectory>${project.build.directory}/staging-linux-specific/modules</outputDirectory>
                            <includeScope>runtime</includeScope>
                            <classifier>linux</classifier>
                        </configuration>
                    </execution>
                    <execution>
                        <id>copy-windows-dependencies</id>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>

<outputDirectory>${project.build.directory}/staging-windows-specific/modules</outputDirectory>
                            <includeScope>runtime</includeScope>
                            <classifier>win</classifier>
                        </configuration>
                    </execution>
                </executions>
            </plugin>


Note the classifier filters which allow windows/linux specific files to be
separated and stored in different staging areas. The OS-agnostic staging
area uses exludes, while the OS-specific areas use includes.

Finally, the assemblies are created with multiple maven assembly xml files
which merge together the common staging area with the OS-specific staging
area corresponding to the assembly.

The result is a single OS-agnostic build which will produce one artifact
per OS platform assembly. Resulting assemblies are ready to be run on their
respective OSes.   It also allows building a single larger package which
includes all OSes.

I've tested it on different build agents and it works well.

Hopefully this classifier trick will help or inspire someone else :)

Cheers, and thanks again for sharing your knowledge about JPackage! I am
still looking into that as it looks promising in the future. Especially for
creating packages that include the JVM, which is by the way a limitation of
the approach I presented here. It requires the user to have Java 11
installed.

*Nicolas Therrien*

Senior Software Developer

*[image:
https://www.motorolasolutions.com/content/dam/msi/images/logos/corporate/msiemailsignature.png]*

*o*: +1.819.931.2053


On Wed, Feb 20, 2019 at 2:50 PM Sverre Moe <sverre.moe at gmail.com> wrote:

> You could use the new jpackage to create a native runtime of your
> application.
> The jpackager is now targeted for JDK 13, but can still be used to create
> a native Java 11 application.
>
> You can download an EA build of JDK 13 with jpackage
> http://jdk.java.net/jpackage/
> <https://urldefense.proofpoint.com/v2/url?u=http-3A__jdk.java.net_jpackage_&d=DwMFaQ&c=q3cDpHe1hF8lXU5EFjNM_A&r=P3_1pTtMQK06fFymYIWbyyzVU6nc0CcwfuZhLhexammvaiCaU0ieHeI7BWvfbbjE&m=mIHIDl0OJMK77Y6JKmQei_6m8TKZmtD6WMu5i-qKU4w&s=v_u06Y0rRkWwAbDFChmSIvZzh8ewYjt9_n8HplXNlu0&e=>
>
> You would need to build on each platform, Linux, Windows, Mac.
>
> You mentioned you use Maven. When Java 9 came out I had already moved over
> to Gradle, so not familiar with the maven configuration.
> Here is a Gradle task to create a Java 11 runtime using jlink with the
> Java 11 jmods
>
> task createRuntime(type: Exec) {
>     dependsOn installDist
>
>     inputs.dir(installDist.outputs.files.singleFile)
>     outputs.dir("${buildDir}/runtime")
>
>     doFirst {
>         delete "${buildDir}/runtime"
>     }
>
>     def libDir = new File(installDist.outputs.files.singleFile, "lib").path
>
>     commandLine '/usr/java/jdk-11/bin/jlink',
>         '--module-path', "/usr/java/jdk-11/jmods:${libDir}",
>         '--add-modules', 'eu.yourmodule.application',
>         '--output', "${buildDir}/runtime"
> }
>
> You then use this runtime with jpackage to create a native application
> image or installer.
>
> task createPackage(type: Exec) {
>     dependsOn createRuntime
>
>     commandLine '/usr/java/jdk-13/bin/jpackage', 'create-installer',
>         '--verbose',
>         '--force',
>         '--name', project.name
> <https://urldefense.proofpoint.com/v2/url?u=http-3A__project.name&d=DwMFaQ&c=q3cDpHe1hF8lXU5EFjNM_A&r=P3_1pTtMQK06fFymYIWbyyzVU6nc0CcwfuZhLhexammvaiCaU0ieHeI7BWvfbbjE&m=mIHIDl0OJMK77Y6JKmQei_6m8TKZmtD6WMu5i-qKU4w&s=dheMFDeYeOiihMrAt4kytHTxkk4Isp14YeMd4phKINc&e=>
> ,
>         '--app-version', project.version,
>         '--module', "${mainClassName}",
>         '--resource-dir', "${buildDir}/package",
>         '--runtime-image', "${buildDir}/runtime",
>         '--output', "${buildDir}/native"
> }
>
> /Sverre
>
> Den ons. 20. feb. 2019 kl. 19:57 skrev Nicolas Therrien <
> nicolas.therrien at motorolasolutions.com>:
>
>> Hi!
>>
>> What is the proper way to create distributable packages of a JavaFx
>> Application?
>>
>> I have a Java 11 application which I build as a module. The distribution
>> includes a "modules" folder with all dependencies in it, and a script to
>> launch the module.
>>
>> This assembly works if I build it on the same machine as I am going to be
>> running it on. However, I realized that depending on which build agent the
>> assembly is going to be created, the platform specific javafx dependencies
>> may not match the target assembly. For example, if the build agent is a
>> linux build agent, the windows and mac assembly contains linux javafx
>> runtime.
>>
>> Maven will always pull the platform-specific libraries of the system it is
>> running on.
>>
>> This was not a problem when JavaFx was part of the JDK since the correct
>> runtime libraries were installed on the system already.
>>
>> What is the correct way to create a windows or linux package in a build
>> platform independent way?
>>
>> I found an article which showed how to force maven to include all
>> platforms
>> as dependencies, but then I have to add dependency on each transitive
>> library. Sounds like a lot of trouble for a simple task.
>>
>> How do you guys package your apps for various platforms?
>>
>> *Nicolas Therrien*
>>
>> Senior Software Developer
>>
>> *[image:
>>
>> https://www.motorolasolutions.com/content/dam/msi/images/logos/corporate/msiemailsignature.png]*
>>
>> *o*: +1.819.931.2053
>>
>


More information about the openjfx-dev mailing list