Maven, JavaFX, Launch4J-Maven-plugin – How to bundle a JRE?

Im building a small app in JavaFX using maven and openJDK 12. However, I need my .Jar to contain a bundled JRE so it can run on windows OS without downloading a proper JRE.

Im also using launch4j-maven-plugin

I tried several solutions here on SOF but no success. Some topics mentioned maven-shade-plugin but it didnt work for me. I couldnt pack external folders with it.

The current POM I have, do the job partially:

  • It packs the “C:/Program Files/Java/openjdk-12.0.2_windows-x64_bin/bin” folder inside the .jar but the “.exes” arent included, which is bad.

  • It packs the dependencies of POM inside the .jar

  • launcher4j-maven packs it all in a .exe

What I want is to pack the JRE inside the .jar and set launcher4J to use it. Would someone help me? I also need this to work because javaFX is being a pain to execute in users/clients computers.

Does the JRE has to be outside the .exe? if yes, then how can I set maven to do that for me?

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>br.sky</groupId>
    <artifactId>Maven-FX</artifactId>
    <version>2.0</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>12</maven.compiler.source>
        <maven.compiler.target>12</maven.compiler.target>
    </properties>

    <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>


        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-graphics </artifactId>
            <version>11.0.2</version>
            <classifier>win</classifier>
        </dependency>

        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx</artifactId>
            <version>11.0.2</version>
            <type>pom</type>
        </dependency>
    </dependencies>

    <build>

        <resources>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
            <resource>
                <filtering>true</filtering>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/application.properties</include>
                </includes>
            </resource>
        </resources>
        <plugins>

            <plugin>
                <artifactId>maven-resources-plugin</artifactId>
                <version>3.1.0</version>
                <executions>
                    <execution>
                        <id>copy-resources</id>
                        <!-- here the phase you need -->
                        <phase>validate</phase>
                        <goals>
                            <goal>copy-resources</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${basedir}/target/JRE</outputDirectory>
                            <resources>
                                <resource>
                                    <directory>C:/Program Files/Java/openjdk-12.0.2_windows-x64_bin/bin</directory>
                                    <filtering>true</filtering>
                                </resource>
                            </resources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>


            <plugin>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-maven-plugin</artifactId>
                <version>0.0.3</version>
                <configuration>
                    <mainClass>br.sky.main.Main</mainClass>
                    <executable>C:Program FilesJavaopenjdk-12.0.2_windows-x64_binbinjava.exe</executable>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.1.2</version>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <mainClass>br.sky.main.Main</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>

            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>3.1.1</version>
                <configuration>
                    <nonFilteredFileExtensions>
                        <nonFilteredFileExtension>exe</nonFilteredFileExtension>
                        <nonFilteredFileExtension>dll</nonFilteredFileExtension>
                    </nonFilteredFileExtensions>

                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <mainClass>br.sky.main.Main</mainClass>
                        </manifest>
                    </archive>
                    <fileSet>
                        <directory>${basedir}/target/JRE</directory>
                        <outputDirectory>/jre/</outputDirectory>
                        <includes>
                            <include>/jre</include>
                        </includes>
                    </fileSet>

                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id> <!-- this is used for inheritance merges -->
                        <phase>package</phase> <!-- bind to the packaging phase -->
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>




            <plugin>
                <groupId>com.akathist.maven.plugins.launch4j</groupId>
                <artifactId>launch4j-maven-plugin</artifactId>
                <version>1.7.25</version>
                <executions>
                    <execution>
                        <id>l4j-clui</id>
                        <phase>package</phase>
                        <goals>
                            <goal>launch4j</goal>
                        </goals>
                        <configuration>
                            <headerType>gui</headerType>
                            <outfile>${project.build.directory}/${project.artifactId}-${project.version}.exe</outfile>
                            <jar>${project.build.directory}/${project.artifactId}-${project.version}-jar-with-dependencies.jar</jar>
                            <errTitle>Maven FX</errTitle>
                            <classPath>
                                <mainClass>br.sky.main.Main</mainClass>
                                <addDependencies>true</addDependencies>
                            </classPath>
                            <jre>
                                <path>./jre</path>
                                <minVersion>11.0.1</minVersion>
                            </jre>
                        </configuration>
                    </execution>
                </executions>
            </plugin>


        </plugins>
    </build>
</project>

Relevant SOF topics:

How to get the JRE to bundle with launch4j?

Bundle a JRE into an exe using Launch4J

https://openjfx.io/openjfx-docs/#install-javafx

https://github.com/lukaszlenart/launch4j-maven-plugin/blob/master/src/main/resources/README.adoc

Answer

This was viewed 108 times in 30 days. So I will post the solution that Ive found and im currently using.

I followed the solution by the user ‘José Pereda’ at https://stackoverflow.com/a/54065502/2280645

Using the OpenJFX and https://github.com/beryx/badass-runtime-plugin

However, In this answer, Im showing a few options that wasnt clearer for me and I bet it isnt clear for students or devs starting with JavaFX:

  • Added Modules in javaFX{} : modules = [ ‘javafx.controls’,’javafx.graphics’, ‘javafx.fxml’ ] to avoid compilation erros and failure when jPackage finishes creating the setup.

  • Set up the variable jpackageHome = ‘C:/Program Files/Java/openjdk-14-jpackage+1-49_windows-x64_bin/’ to point out where the jPackage is. This is useful when you are using another JDK as the main build to other projects or for the IDE itself. Which is my case.

  • imageOptions = [‘–icon’, ‘src/main/resources/images/logo.ico’] to set up the icon properly. I didnt know that windows required a .ico instead of a .png

  • compileJava.options.encoding Because since I use latin symbols, it broke several files of mine.

I hope these tips along with Jose pereda answer will save time of others who are lost or new to JavaFx.


plugins {
    id 'java'
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.0.8'
    id 'org.beryx.runtime' version '1.7.0'
    id "com.github.johnrengelman.shadow" version "5.1.0"
}

repositories {
    mavenCentral()
}

ext {
    openJfxVersion = '13'
}

dependencies {
    compile 'org.openjfx:javafx-base:${openJfxVersion}:win'
    compile 'org.openjfx:javafx-controls:${openJfxVersion}:win'
    compile 'org.openjfx:javafx-graphics:${openJfxVersion}:win'
    compile 'org.openjfx:javafx-fxml:13'
}


javafx {
    version = "13"
    modules = [ 'javafx.controls','javafx.graphics', 'javafx.fxml'  ]
}

mainClassName = 'Main'

runtime {
    options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']

    jpackage {
        jpackageHome = 'C:/Program Files/Java/openjdk-14-jpackage+1-49_windows-x64_bin/'


        if(org.gradle.internal.os.OperatingSystem.current().windows) {
            installerType = 'msi'
            imageOptions = ['--icon', 'src/main/resources/images/logo.ico']
            installerOptions = ['--win-per-user-install',
                '--win-dir-chooser',
                '--win-menu',
                '--win-shortcut',
                '--verbose',
                '--description','x ',
                '--name', 'x',
                '--vendor','x',
                '--win-upgrade-uuid','x']
        }
    }

}

compileJava {
    compileJava.options.encoding = 'ISO-8859-1'
    doFirst {
        options.compilerArgs = [
                '--module-path', classpath.asPath,
                '--add-modules', 'javafx.controls,javafx.fxml'
        ]
    }
}

run {
    doFirst {
        jvmArgs = [
                '--module-path', classpath.asPath,
                '--add-modules', 'javafx.controls,javafx.fxml'
        ]
    }
}



group = 'br.x'
version = '0.1'

tasks.withType(JavaCompile) {
    options.encoding = 'ISO-8859-1'
}