# JavaFX jar mit Maven



## psp3006 (13. Dez 2020)

Abend,

nachdem mir schon bei meinen anderen "Problem" geholfen wurde, habe ich jetzt das nächste.

Ich habe mit JavaFX eine kleine Test-Gui erzeugt und möchte diese mittels`java -jar gui-0.1.0-SNAPSHOT.jar` ausführen.
Bekomme aber immer die Meldung `no main manifest attribute, in .\gui-0.1.0-SNAPSHOT.jar`

Mittels `mvn exec:exec` kann ich die Anwendung ausführen.



Spoiler: pom.xml



[CODE lang="xml"]<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>


    <groupId>com.example.calc</groupId>
    <artifactId>gui</artifactId>
    <version>0.1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>11</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
            <version>11</version>
        </dependency>
        <dependency>
            <groupId>com.example.calc</groupId>
            <artifactId>operator</artifactId>
            <version>1.0.0-SNAPSHOT</version>
            <type>jar</type>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <release>11</release>
                    <source>11</source>
                    <target>11</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.6.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>exec</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <skip>false</skip>
                    <executable>java</executable>
                    <arguments>
                        <argument>--module-path</argument> <!-- or -p  -->
                        <modulepath/>
                        <!-- automatically creates the modulepath using all project dependencies,
                             also adding the project build directory -->
                        <argument>--module</argument>  <!-- or -m -->
                        <argument>com.example.calc.gui/com.example.calc.gui.GuiMain</argument>
                    </arguments>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
[/CODE]





Spoiler: GuiMain.java



[CODE lang="java"]package com.example.calc.gui;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;


public class GuiMain extends Application {

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

    @Override
    public void start(Stage primaryStage) throws Exception {
        primaryStage.setTitle("Calculator - FirstGUI");

        Parent root = FXMLLoader.load(getClass().getResource("/calculator.fxml"));

        Scene scene = new Scene(root, 400, 200);

        primaryStage.setScene(scene);
        primaryStage.show();
    }

}
[/CODE]





Spoiler: module-info



[CODE lang="java"]module com.example.calc.gui {
    requires javafx.fxml;
    requires javafx.controls;

    requires com.example.calc.operator;

    exports com.example.calc.gui to javafx.graphics;
}
[/CODE]




Zusätzlich habe ich es euch auch wieder in ne ZIP-Datei gepackt.

Vielleicht kann mir ja wer helfen.


----------



## mihe7 (14. Dez 2020)

Ich meine, Du solltest das javafx-maven-plugin verwenden (https://github.com/openjfx/javafx-maven-plugin). Hier das Beispiel-POM dazu: https://github.com/openjfx/samples/blob/master/HelloFX/Maven/hellofx/pom.xml


----------



## kneitzel (14. Dez 2020)

Auch nur zur Erläuterung:

Dein jar File enthält nicht die main class. Denn die gibst Du nicht an. Du hast da nur was bei einem exec plugin angegeben. Das macht aber nur eine direkte Ausführung und beeinflusst nicht den Bau des jar Files. Was Du also brauchen würdest, wäre sowas wie:

```
<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>com.maventest.App</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
```

Aber bei JavaFX würde Dir das nicht viel nützen, es sei denn Du arbeitest mit einem Java, das bereits ein JavaFX enthält. (Bellsoft full JDK z.B.)

Daher solltest Du so wie es @mihe7 bereits gesagt hat, das javafx plugin nutzen.

Das wird auch schon auf openjfx.io entsprechend gezeigt: https://openjfx.io/openjfx-docs/#maven

Wenn man etwas weiter geben möchte, dann sollte man aber auch das jlink entsprechend mit konfigurieren und dann landen wir bei etwas wie:




oder auch 





Das erste zeigt eine JavaFX Applikation, die ich von eclipse Project build zu einer Maven Applikation mache. Enthät aber auch direkt
- das Ausführen und bauen des Images
- Das weitere Verarbeiten des Images mit JPackage (ab OpenJDK 14)

Und ganz wichtig, nur um es einmal ganz deutlich zu sagen:
Du baust dann kein JAR mehr zu, weiter geben, denn dies ist so leider recht problematisch. Statt dessen baust Du ein sogenanntes Images und dieses gibst Du dann weiter.


----------



## psp3006 (14. Dez 2020)

Danke euch erstmal. Werde mir die Videos mal bei Gelegenheit anschauen


----------



## kneitzel (14. Dez 2020)

Ja, wobei ich die Videos noch prüfen muss ... bei meinem Videos hat teilweise meine Schnittsoftware mich etwas geärgert und bei mindestens zwei Videos sind Teile ohne Bild ... Was beim Export passiert sein muss, denn ich habe ja das ganze Video geprüft / geschnitten ... Da wird es jetzt nach und nach Ersatz für geben ...


----------



## kneitzel (14. Dez 2020)

Die beiden betroffenen Videos habe ich jetzt einmal neu erstellt und neu eingestellt (Ersetzen des original Videos geht leider nicht bei YouTube).
Wobei diese beiden Videos nicht betroffen waren. IT Erklärbär istohne großes Editieren entstanden und das zweite Video ist auf Linux entstanden meine ich - also ohne irgend welche buggy Windows Software ...  Schade nur, dass ich da auch noch Geld für Schrott ausgegeben habe - Open Source Lösungen gibt es auch vernünftige ...


----------



## psp3006 (15. Dez 2020)

Abend, 
habe es nun geschafft mit den `javafx-maven-plugin` geschafft eine jar zubauen die auch ausführbar ist. Das Video habe ich mir dennoch mal angeschaut, dann weis ich jetzt auch was es noch für ne alternative gibt. 
Danke euch


----------



## psp3006 (15. Dez 2020)

Ich hab da nochmal ne frage. 
Wenn ich jetzt eine Dependency aus der fertigen Jar-Datei ausschließen möchte , so das ich dieses Dependeny immer als seperate Jar-Datei im ausführenden Ordner liegen haben muss.


----------



## kneitzel (16. Dez 2020)

Also da Du uns keine Informationen gegeben hast, wie Du nun dein jar File baust, ist das so pauschal nicht zu beantworten.

Das jar File, das maven in der Regel baut, ist kein uber / fat jar, d.h. die Abhängigkeiten sind nicht enthalten. Dein Hinweis auf das javafx-maven-plugin (von org.openjfx nehme ich an - nicht das du irgendwas anderes nutzt ... Aber auf dieses plugin wurdest Du hier ja hingewiesen) ist wenig hilfreich, denn dieses plugin hat eben meiner Meinung nach auch keine uber jar Funktionalität. Es bietet das run und jlink Ziel. Die Entwickler sehen die Erstellung eines Runtime Images vor zur Weitergabe.

So ein uber jar kann z.B. mit dem maven shade plugin gebaut werden. Dieses bietet filter und artifactSets:


			Maven Shade Plugin - Selecting Contents for Uber JAR
		



			Apache Maven Shade Plugin – shade:shade
		


Falls Du das nicht nutzt gibt es ggf. auch irgendwelche "Tricksereien" um z.B. eine Abhängigkeit als provided einzubinden um es dann aber an anderer Stelle beim Ausführen wieder mit in den classpath mit aufzunehmen ... Das wäre das Vorgehen bei Application Servern, die ja gewisse Libraries immer dabei haben so dass diese nicht mitgegeben werden dürfen. Im JavaFX Umfeld sehe ich dies aber eher als dubios an muss ich gestehen. Zumindest verkompliziert es das Projekt. Daher:

Ich bleibe weiterhin dabei: Ich sehe da irgendwie keinen Sinn in so einem Vorgehen. https://openjfx.io/openjfx-docs/ zeigt auf, wie aus Sicht der "JavaFX Entwickler" die Runtime Images gebaut werden sollten incl. der Funktionalität des plugins, damit es eben eine einfache, kleine pom.xml bleibt, die auch weniger versierte Entwickler verstehen können und die einen schnellen Einstieg ohne viel erlernen zu müssen, bietet. Das heißt nicht, dass es nicht auch andere Wege geben sollte, aber da sollte man sich dann aus meiner Sicht auf jeden Fall tiefer einlesen und verstehen, was man da macht, denn das ist dann in der Regel ein weniger unterstützter Weg, d.h. weniger "Dokumentation" bezüglich des Anwendungsbereiches und weniger Leute, die da intensiv Erfahrungen gesammelt haben....


----------



## psp3006 (23. Dez 2020)

Hi, sorry für die späte Antwort. Inzwischen habe ich es mit dem Maven Shade Plugin hinbekommen.
Dafür habe ich das Maven Shade Plugin


```
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>2.4.3</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
            <configuration>
                <artifactSet>
                    <excludes>
                        <exclude>mein.package:MainClass</exclude>
                    </excludes>
                </artifactSet>
                <transformers>
                    <!-- add Main-Class to manifest file -->
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                        <mainClass>${main.class}</mainClass>
                    </transformer>
                </transformers>
            </configuration>
        </execution>
    </executions>
</plugin>
```

und das Maven Jar Plugin wie folgt konfiguriert

```
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>3.2.0</version>
    <configuration>
        <archive>
            <manifest>
                <mainClass>${main.class}</mainClass>
                <addClasspath>true</addClasspath>
            </manifest>
        </archive>
    </configuration>
</plugin>
```


----------

