javamavenjavafxlaunch4j

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:

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 Files\Java\openjdk-12.0.2_windows-x64_bin\bin\java.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


Solution

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

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