Merge pull request #6 from kneitzel/direct-jpackage

Direct jpackage
This commit is contained in:
Konrad Neitzel 2023-03-21 16:35:14 +01:00 committed by GitHub
commit b438665f83
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 156 additions and 118 deletions

View File

@ -2,9 +2,14 @@
Example Maven Project for a JavaFX Application. Example Maven Project for a JavaFX Application.
Maven modules are configured so that even Images are built (including JPackage app-image). This projects includes multiple plugins:
- Static code analysis with PMD and Spotbugs
- Check of dependency updates during build
- Build of an App-Image using JPackage
Project includes PMD and spotbugs! The application is no longer a modular application so there are no problems with dependencies that are not providing a
module-info.
**Important**: Using moditect to add module descriptions is not required. New solution to create images through jpackage will be commited soon. ** Build the Image **
Check branch direct-jpackage to see the current test project I build. To build the image, the profile Image must be used:
```./mvnw -DImage install```

183
pom.xml
View File

@ -17,17 +17,17 @@
<link.name>${project.artifactId}</link.name> <link.name>${project.artifactId}</link.name>
<launcher>${project.artifactId}</launcher> <launcher>${project.artifactId}</launcher>
<appName>${project.artifactId}</appName> <appName>${project.artifactId}</appName>
<main.class>de.kneitzel.JavaFXApp</main.class> <main.class>de.kneitzel.Main</main.class>
<main.module>FXAppModule</main.module>
<java.version>17</java.version> <java.version>17</java.version>
<required.maven.version>3.6.3</required.maven.version> <required.maven.version>3.6.3</required.maven.version>
<jar.filename>${project.artifactId}-${project.version}</jar.filename>
<!-- Dependency versions --> <!-- Dependency versions -->
<junit.version>5.9.1</junit.version> <javafx.version>19</javafx.version>
<lombok.version>1.18.26</lombok.version> <jetbrains.annotations.version>24.0.1</jetbrains.annotations.version>
<javafx.version>19.0.2.1</javafx.version> <junit.version>5.9.2</junit.version>
<jetbrains.annotations.version>23.1.0</jetbrains.annotations.version>
<lombok.version>1.18.26</lombok.version> <lombok.version>1.18.26</lombok.version>
<mockito.version>5.2.0</mockito.version>
<!-- Plugin dependencies --> <!-- Plugin dependencies -->
<maven.clean.plugin>3.2.0</maven.clean.plugin> <maven.clean.plugin>3.2.0</maven.clean.plugin>
@ -43,7 +43,7 @@
<moditect.maven.plugin>1.0.0.RC2</moditect.maven.plugin> <moditect.maven.plugin>1.0.0.RC2</moditect.maven.plugin>
<jpackage.maven.plugin>0.1.3</jpackage.maven.plugin> <jpackage.maven.plugin>0.1.3</jpackage.maven.plugin>
<maven.pmd.version>3.16.0</maven.pmd.version> <maven.pmd.version>3.16.0</maven.pmd.version>
<pmd.version>6.52.0</pmd.version> <pmd.version>6.55.0</pmd.version>
<codehaus.version.plugin>2.11.0</codehaus.version.plugin> <codehaus.version.plugin>2.11.0</codehaus.version.plugin>
<spotbugs.maven.plugin>4.7.2.0</spotbugs.maven.plugin> <spotbugs.maven.plugin>4.7.2.0</spotbugs.maven.plugin>
<spotbugs.version>4.7.3</spotbugs.version> <spotbugs.version>4.7.3</spotbugs.version>
@ -52,10 +52,12 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>${java.version}</maven.compiler.source> <maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target> <maven.compiler.target>${java.version}</maven.compiler.target>
<maven.compiler.release>${java.version}</maven.compiler.release>
</properties> </properties>
<dependencies> <dependencies>
<!-- JavaFX dependencies -->
<dependency> <dependency>
<groupId>org.openjfx</groupId> <groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId> <artifactId>javafx-controls</artifactId>
@ -66,12 +68,18 @@
<artifactId>javafx-graphics</artifactId> <artifactId>javafx-graphics</artifactId>
<version>${javafx.version}</version> <version>${javafx.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.openjfx</groupId> <groupId>org.openjfx</groupId>
<artifactId>javafx-web</artifactId> <artifactId>javafx-web</artifactId>
<version>${javafx.version}</version> <version>${javafx.version}</version>
</dependency> </dependency>
<!-- Lombok -->
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
@ -79,6 +87,34 @@
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- JUnit 5 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- Mockito -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<!-- Dependency used for @NotNull / @Nullable --> <!-- Dependency used for @NotNull / @Nullable -->
<dependency> <dependency>
<groupId>org.jetbrains</groupId> <groupId>org.jetbrains</groupId>
@ -87,15 +123,10 @@
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
<finalName>${jar.filename}</finalName>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
@ -288,13 +319,13 @@
</activation> </activation>
<build> <build>
<plugins> <plugins>
<!-- Copy dependencies --> <!-- Copy dependencies -->
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId> <artifactId>maven-dependency-plugin</artifactId>
<version>${maven.dependency.plugin}</version> <version>${maven.dependency.plugin}</version>
<executions> <executions>
<!-- erstmal Abhängigkeiten für den Class-Path kopieren -->
<execution> <execution>
<id>copy-dependencies</id> <id>copy-dependencies</id>
<phase>package</phase> <phase>package</phase>
@ -303,98 +334,69 @@
</goals> </goals>
<configuration> <configuration>
<outputDirectory>${project.build.directory}/modules</outputDirectory> <outputDirectory>${project.build.directory}/modules</outputDirectory>
<includeScope>runtime</includeScope>
<overWriteReleases>false</overWriteReleases> <overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots> <overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer> <overWriteIfNewer>true</overWriteIfNewer>
</configuration> </configuration>
</execution> </execution>
<!-- dazu noch das Projekt-JAR -->
<execution>
<id>copy</id>
<phase>install</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/modules</outputDirectory>
<artifactItems>
<artifactItem>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<type>${project.packaging}</type>
<destFileName>${project.build.finalName}.jar</destFileName>
</artifactItem>
</artifactItems>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions> </executions>
</plugin> </plugin>
<!-- Build image -->
<plugin>
<groupId>org.moditect</groupId>
<artifactId>moditect-maven-plugin</artifactId>
<version>${moditect.maven.plugin}</version>
<executions>
<execution>
<id>add-module-info-to-dependencies</id>
<phase>package</phase>
<configuration>
<outputDirectory>${project.build.directory}/modules</outputDirectory>
<overwriteExistingFiles>true</overwriteExistingFiles>
<!-- Beispiel wie eine Dependency ohne module-info diese bekommen kann! -->
<!--
<modules>
<module>
<artifact>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
</artifact>
<moduleInfo>
<name>org.json</name>
</moduleInfo>
</module>
</modules>
-->
<module>
<mainClass>${main.class}</mainClass>
<moduleInfoFile>${project.build.sourceDirectory}/module-info.java</moduleInfoFile>
</module>
<jdepsExtraArgs>
--ignore-missing-deps
</jdepsExtraArgs>
</configuration>
<goals>
<goal>add-module-info</goal>
</goals>
</execution>
<execution>
<id>create-runtime-image</id>
<phase>package</phase>
<goals>
<goal>create-runtime-image</goal>
</goals>
<configuration>
<modulePath>
<path>${project.build.directory}/modules</path>
</modulePath>
<modules>
<module>${main.module}</module>
</modules>
<launcher>
<name>${launcher}</name>
<module>${main.module}</module>
</launcher>
<compression>2</compression>
<bindServices>true</bindServices>
<jarInclusionPolicy>APP_WITH_DEPENDENCIES</jarInclusionPolicy>
<stripDebug>true</stripDebug>
<outputDirectory>${project.build.directory}/jlink-image</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!-- Build JPackage App-Image -->
<plugin> <plugin>
<groupId>com.github.akman</groupId> <groupId>com.github.akman</groupId>
<artifactId>jpackage-maven-plugin</artifactId> <artifactId>jpackage-maven-plugin</artifactId>
<version>${jpackage.maven.plugin}</version> <version>${jpackage.maven.plugin}</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jpackage</goal>
</goals>
<configuration> <configuration>
<name>${appName}</name> <name>${appName}</name>
<type>IMAGE</type> <type>IMAGE</type>
<runtimeimage>${project.build.directory}/jlink-image</runtimeimage> <modulepath>
<module>${main.module}/${main.class}</module> <dependencysets>
<dependencyset>
<includenames>
<includename>javafx\..*</includename>
</includenames>
</dependencyset>
</dependencysets>
</modulepath>
<addmodules>
<addmodule>javafx.controls</addmodule>
<addmodule>javafx.graphics</addmodule>
<addmodule>javafx.fxml</addmodule>
<addmodule>javafx.web</addmodule>
</addmodules>
<mainclass>${main.class}</mainclass>
<input>${project.build.directory}/modules</input>
<mainjar>${jar.filename}.jar</mainjar>
</configuration> </configuration>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>jpackage</goal>
</goals>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
@ -403,5 +405,4 @@
</profile> </profile>
</profiles> </profiles>
</project> </project>

View File

@ -1,30 +1,30 @@
package de.kneitzel; package de.kneitzel;
import javafx.application.Application; import javafx.application.Application;
import javafx.event.ActionEvent; import javafx.fxml.FXMLLoader;
import javafx.event.EventHandler; import javafx.scene.Parent;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage; import javafx.stage.Stage;
import java.io.IOException;
public class JavaFXApp extends Application { public class JavaFXApp extends Application {
@Override @Override
public void start(Stage primaryStage) { public void start(Stage primaryStage) {
try {
primaryStage.setTitle("Hello World!"); primaryStage.setTitle("Hello World!");
Button btn = new Button(); FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("MainWindow.fxml"));
btn.setText("Say 'Hello World'"); Parent root = fxmlLoader.load();
btn.setOnAction(e -> System.out.println("Hello World!")); primaryStage.setScene(new Scene(root));
StackPane root = new StackPane();
root.getChildren().add(btn);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show(); primaryStage.show();
} catch (Exception ex) {
System.out.println("Exception: " + ex.getMessage());
ex.printStackTrace();
}
} }
public static void main(String[] args) { public static void main(String[] args) {
launch(args); launch(args);
} }
} }

View File

@ -0,0 +1,30 @@
package de.kneitzel;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import java.net.URL;
import java.util.ResourceBundle;
public class MainWindow implements Initializable {
@FXML
private TextField textField;
public Button button;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
if (button == null) {
textField.setText("Button is null");
} else {
textField.setText("Button is not null");
}
}
@FXML
private void onButtonClick(ActionEvent actionEvent) {
}
}

View File

@ -1,9 +0,0 @@
module FXAppModule {
requires javafx.base;
requires javafx.graphics;
requires javafx.controls;
requires javafx.web;
exports de.kneitzel;
opens de.kneitzel;
}

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane prefHeight="127.0" prefWidth="209.0" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.kneitzel.MainWindow">
<children>
<Button fx:id="button" layoutX="44.0" layoutY="70.0" mnemonicParsing="false" onAction="#onButtonClick" text="Button" />
<TextField fx:id="textField" layoutX="14.0" layoutY="24.0" />
</children>
</AnchorPane>