This commit is contained in:
Konrad Neitzel 2024-03-27 11:50:48 +01:00
commit 71e9b09893
7 changed files with 224 additions and 119 deletions

24
LICENSE.md Normal file
View File

@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <https://unlicense.org>

View File

@ -2,12 +2,50 @@
Example Maven Project for a JavaFX Application.
Maven modules are configured so that even Images are build (including JPackage app-image).
**The application is no longer a modular application so there are no problems with dependencies that are not providing a
module-info.**
Project includes PMD and spotbugs!
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
- JavaFX plugin to start application
**Important** All commands following should be issued in the root directoy of the project (the directory where you find the pom.xml)
*Quick Start*
- Simply download a zip file of this project and unzip it somewhere on your computer
- open the opm.xml and change the settings at the start of the document to fit with your project
Branches shows,
- including log4j
- including slf4j
This is just for testing purpose / was requiried during threads in http://java-forum.org.
*How to use this project*
**build the application**
To build the application, maven / the maven wrapper can be used. Simply do a
```./mvnw package```
to build the application.
(simply call mvnw instead of ./mvnw on windows!)
**Clean up**
To clean up the project, call
```./mvnw package```
**Start the application from commandline**
```./mvnw javafx:run```
**Build the Image**
To build the image, the profile Image must be used:
```./mvnw -DImage install```
**Important** You cannot build an image using the javafx plugin. The javafx plugin would require that you build a modular
Java application and all dependencies providing a module description.
**Static code analysis**
The static code analysis is done when you build the application. The results can be found in
- ./target/pmx.xml
- ./target/spotbugsXml.xml

189
pom.xml
View File

@ -17,17 +17,17 @@
<link.name>${project.artifactId}</link.name>
<launcher>${project.artifactId}</launcher>
<appName>${project.artifactId}</appName>
<main.class>de.kneitzel.JavaFXApp</main.class>
<main.module>FXAppModule</main.module>
<main.class>de.kneitzel.Main</main.class>
<java.version>17</java.version>
<required.maven.version>3.6.3</required.maven.version>
<jar.filename>${project.artifactId}-${project.version}</jar.filename>
<!-- Dependency versions -->
<junit.version>5.9.1</junit.version>
<lombok.version>1.18.26</lombok.version>
<javafx.version>19.0.2.1</javafx.version>
<jetbrains.annotations.version>23.1.0</jetbrains.annotations.version>
<jetbrains.annotations.version>24.0.1</jetbrains.annotations.version>
<junit.version>5.9.3</junit.version>
<lombok.version>1.18.26</lombok.version>
<mockito.version>5.3.1</mockito.version>
<!-- Plugin dependencies -->
<maven.clean.plugin>3.2.0</maven.clean.plugin>
@ -43,8 +43,9 @@
<moditect.maven.plugin>1.0.0.RC2</moditect.maven.plugin>
<jpackage.maven.plugin>0.1.3</jpackage.maven.plugin>
<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>
<javafx.maven.plugin>0.0.8</javafx.maven.plugin>
<spotbugs.maven.plugin>4.7.2.0</spotbugs.maven.plugin>
<spotbugs.version>4.7.3</spotbugs.version>
@ -52,10 +53,12 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<maven.compiler.release>${java.version}</maven.compiler.release>
</properties>
<dependencies>
<!-- JavaFX dependencies -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
@ -66,12 +69,18 @@
<artifactId>javafx-graphics</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-web</artifactId>
<version>${javafx.version}</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
@ -79,6 +88,34 @@
<scope>provided</scope>
</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>
<groupId>org.jetbrains</groupId>
@ -87,15 +124,10 @@
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>${jar.filename}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@ -270,6 +302,15 @@
</executions>
</plugin>
<!-- JavaFX Plugin to start application -->
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>${javafx.maven.plugin}</version>
<configuration>
<mainClass>${main.class}</mainClass>
</configuration>
</plugin>
</plugins>
</build>
@ -288,13 +329,13 @@
</activation>
<build>
<plugins>
<!-- Copy dependencies -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>${maven.dependency.plugin}</version>
<executions>
<!-- erstmal Abhängigkeiten für den Class-Path kopieren -->
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
@ -303,98 +344,69 @@
</goals>
<configuration>
<outputDirectory>${project.build.directory}/modules</outputDirectory>
<includeScope>runtime</includeScope>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</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>
</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>
<groupId>com.github.akman</groupId>
<artifactId>jpackage-maven-plugin</artifactId>
<version>${jpackage.maven.plugin}</version>
<configuration>
<name>${appName}</name>
<type>IMAGE</type>
<modulepath>
<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>
<executions>
<execution>
<phase>package</phase>
<phase>install</phase>
<goals>
<goal>jpackage</goal>
</goals>
<configuration>
<name>${appName}</name>
<type>IMAGE</type>
<runtimeimage>${project.build.directory}/jlink-image</runtimeimage>
<module>${main.module}/${main.class}</module>
</configuration>
</execution>
</executions>
</plugin>
@ -403,5 +415,4 @@
</profile>
</profiles>
</project>

View File

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