How to bundle the JavaFX SDK directly in the output jar?

Martin :

Currently I am using a JVM argument when launching my program for it to find the JavaFX libraries like so :

java -javaagent:lib/aspectjweaver-1.9.5.jar -javaagent:lib/spring-instrument-5.2.3.RELEASE.jar --module-path lib/javafx-sdk-13.0.2/lib --add-modules=javafx.controls -jar target/Some_Service-1.0.jar

My POM.xml's plugins section is extremely simple. Aside from the Docker and Launch4j plugins I only have this :

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <executions>
        <execution>
            <goals>
                <goal>repackage</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Is there a way to tell Maven to bundle that whole lib directory (which contains the JavaFX libraries and aspectJ/spring instrument java agents) right in the jar? Doing this would solve the issue of having to carry that lib folder around everywhere I deploy my app! Thanks!

******EDIT******

I messed around with the spring boot maven plugin options and unfortunately my jar still doesn't contain my folder :

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <folders>
            <folder>lib</folder>
        </folders>
        <agent>lib/aspectjweaver-1.9.5.jar</agent>
        <agent>lib/spring-instrument-5.2.3.RELEASE.jar</agent>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>repackage</goal>
            </goals>
        </execution>
    </executions>
</plugin>

******EDIT 2******

I just found an awesome library that eliminates the need for the -javaagent parameters altogether by having you load them programmatically at runtime instead. It looks like the very presence of AspectJ and Spring-Instrument on my classpath is all it needs too! Check it out : https://github.com/subes/invesdwin-instrument.

All I need now is to somehow bundle the JavaFX runtime into my jar instead of referring to it externally using a command line argument.

Slaw :

Instead of the using the JavaFX SDK, declare your dependence on JavaFX in your pom.xml file. Then you can use the maven-shade-plugin to create an executable fat/uber JAR. The appropriate JavaFX JARs (e.g. the graphics JAR file) downloaded from Maven Central embed the needed, platform-specific native code which will be extracted at runtime (e.g. to the user home directory).

Here's a minimal example:

Launcher.java:

package com.example;

import javafx.application.Application;

public class Launcher {

  public static void main(String[] args) {
    Application.launch(App.class, args);
  }
}

App.java:

package com.example;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class App extends Application {

  @Override
  public void start(Stage primaryStage) {
    StackPane root = new StackPane(new Label("Hello, World!"));
    primaryStage.setScene(new Scene(root, 500, 300));
    primaryStage.show();
  }
}

pom.xml:

<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>com.example</groupId>
    <artifactId>javafx-uber-jar</artifactId>
    <version>1.0</version>

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

    <build>
      <plugins>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.1</version>
          <configuration>
              <release>13</release>
          </configuration>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-shade-plugin</artifactId>
          <version>3.2.2</version>
          <executions>
            <execution>
              <phase>package</phase>
              <goals>
                <goal>shade</goal>
              </goals>
              <configuration>
                <transformers>
                  <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                    <mainClass>com.example.Launcher</mainClass>
                  </transformer>
                </transformers>
              </configuration>
            </execution>
          </executions>
        </plugin>

      </plugins>
    </build>

    <dependencies>
      <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-controls</artifactId>
        <version>13.0.2</version>
      </dependency>
    </dependencies>

</project>

Command line:

mvn package

The above will create a platform-specific uber JAR. See this answer for ideas on how to create a cross-platform uber JAR.

Depending on the version of Java you're using to develop your application, you could look into jlink (Java 9+) and/or jpackage (Java 14, early-access) as alternatives to creating a fat/uber JAR file. If you use one of those, consider using the JMOD files of JavaFX (can be found here) as it configures the custom image to handle native code better (i.e. no extraction).


Notice that the main class is not a subclass of Application. This is mandatory for applications which put the JavaFX libraries on the classpath, at least for JavaFX 9-13. The reason for this requirement has to do with the implementation allowing JavaFX applications to not have a main method; if the javafx.graphics module is not on the modulepath it is assumed that "JavaFX components are missing". But that only occurs when the main class and Application class are the same, hence the above workaround.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=11534&siteId=1