JavaFX OpenJFX13 Anwendung exportieren

lam_tr

Top Contributor
Hallo zusammen,

ich habe nun endlich versucht eine OpenJFX Anwendung zum Laufen zu bekommen. Ich habe diesen Source als Beispiel genommen https://github.com/openjfx/samples/

Dieses Projekt enthält
* Diese Gradle Datei:
Code:
plugins {
  id 'application'
  id 'eclipse'
  id 'org.openjfx.javafxplugin' version '0.0.8'
  id 'org.beryx.jlink' version '2.12.0'
}

repositories {
    mavenCentral()
}

javafx {
    version = "13"
    modules = [ 'javafx.controls', 'javafx.fxml' ]
}

mainClassName = "$moduleName/org.openjfx.MainApp"

eclipse {
    classpath {
        file {
            whenMerged {
                entries.findAll { it.properties.kind.equals('lib') }.each {
                    it.entryAttributes['module'] = 'true'
                }
            }
        }
    }
}

jlink {
    options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
    launcher {
        name = 'hellofx'
    }
}

* Warum kann ich die MainApp nicht direkt in Eclipse im "Run As" laufen lassen? Über den Gradle Build lässt sich die Anwendung starten.
* Wenn ich meine Abhängigkeiten direkt über Gradle hole, muss ich dann OpenJFX noch als User Library in Eclipse Project inkludieren, warum?
* Wie kann ich die OpenJFX als jar exportieren? Vermutlich mit Gradle, wie soll der Task aussehen?
In dem OpenJFX Document sind ein paar Begriffe die ich nicht verstanden habe:
* Wofür brauche ich eine Runtime Image, wenn die Abhängigkeiten über Gradle gezogen werden?
* Wofür ist jmods?

Viele Grüße
lam
 

mrBrown

Super-Moderator
Mitarbeiter
Welches der vielen Beispiele aus dem Repo ist es denn?

* Warum kann ich die MainApp nicht direkt in Eclipse im "Run As" laufen lassen? Über den Gradle Build lässt sich die Anwendung starten.
Zumindest in IntelliJ lässt sich das wie gewohnt starten, das sollte mit Eclipse auch möglich sein - da kann vielleicht einer mit Eclipse-Erfahrung was zu sagen.

* Wenn ich meine Abhängigkeiten direkt über Gradle hole, muss ich dann OpenJFX noch als User Library in Eclipse Project inkludieren, warum?
Das gradle-Projekt importieren sollte reichen, händisch irgendwelche Libs eintragen macht das meiste nur kaputt.
Musstest du irgendwas extra über Eclipse einbinden, oder ist das nur die Frage, ob das nötig ist?

* Wie kann ich die OpenJFX als jar exportieren? Vermutlich mit Gradle, wie soll der Task aussehen?
Der "richtige Weg" wäre, mit jlink ein Runtime-Image zu bauen, was dann sowohl das JRE als auch alle nötigen Abhängigkeiten enthält. Das ganze lässt sich über den jlink-Task anstoßen, der Ergebnis liegt dann in build/image, zum starten nimmt man dort im bin-Ordner das entsprechende Skript.

* Wofür brauche ich eine Runtime Image, wenn die Abhängigkeiten über Gradle gezogen werden?
Das Runtime-Image enthält JRE + Libs + deinen Code, ist also ein eigenständig lauffähiges Bundle, was keinerlei Abhängigkeiten zu gradle, Java oder sonstigem mehr enthält :)

* Wofür ist jmods?
Die JDK-Module liegen im jmod-Format vor - wirklich in Berührung kommt man damit aber nicht. Wo wird das denn erwähnt?
 

lam_tr

Top Contributor
Vielen Dank für die Ausführliche Erklärung, das hat ein bisschen Klarheit reingebracht.

Welches der vielen Beispiele aus dem Repo ist es denn?
samples/IDE/Eclipse/Modular/Gradle/

Zumindest in IntelliJ lässt sich das wie gewohnt starten, das sollte mit Eclipse auch möglich sein - da kann vielleicht einer mit Eclipse-Erfahrung was zu sagen.
Beim erfolgreichen Ausführen von build.gradle können die javafx.* Abhängigkeiten immer noch aufgelöst werden, deswegen war meine Annahme dass User Library noch eingerichtet werden muss.

Das gradle-Projekt importieren sollte reichen, händisch irgendwelche Libs eintragen macht das meiste nur kaputt.
Musstest du irgendwas extra über Eclipse einbinden, oder ist das nur die Frage, ob das nötig ist?
Das mit dem Libs einbinden habe ich von hier https://openjfx.io/openjfx-docs/ aber für non modular projects ide

Der "richtige Weg" wäre, mit jlink ein Runtime-Image zu bauen, was dann sowohl das JRE als auch alle nötigen Abhängigkeiten enthält. Das ganze lässt sich über den jlink-Task anstoßen, der Ergebnis liegt dann in build/image, zum starten nimmt man dort im bin-Ordner das entsprechende Skript.
Kann man das hier als Beispiel nehmen?https://stackoverflow.com/questions...oy-a-javafx-11-desktop-application-with-a-jre
Oder hast du gute Referenzen hierzu für mich parat?

Die JDK-Module liegen im jmod-Format vor - wirklich in Berührung kommt man damit aber nicht. Wo wird das denn erwähnt?
Ich habe es nur auf der openjfx docu Seite im Rahmen von Runtime Images gelesen.

Grüße
lam
 

mrBrown

Super-Moderator
Mitarbeiter
Ich habs grad nur mit CommandLine/Modular/Gradle, das läuft auf jeden Fall.

Beim erfolgreichen Ausführen von build.gradle können die javafx.* Abhängigkeiten immer noch aufgelöst werden, deswegen war meine Annahme dass User Library noch eingerichtet werden muss.
Da fehlt ein *nicht*?
Ich kann nur für IntelliJ sprechen, da klappt das ohne weiteres problemlos - und in Eclipse sollte das nicht anders sein, das führt sonst nur zu Problemen

Das mit dem Libs einbinden habe ich von hier https://openjfx.io/openjfx-docs/ aber für non modular projects ide
Das sollte mit gradle/maven-Projekten nicht nötig sein, genau den Teil sollen die ja abnehmen.

Kann man das hier als Beispiel nehmen?https://stackoverflow.com/questions...oy-a-javafx-11-desktop-application-with-a-jre
Oder hast du gute Referenzen hierzu für mich parat?
Kommt drauf an wozu du ein Beispiel willst? ;)
In dem Beispielprojekte, welches du ja schon ausprobiert hast, einfach nur ./gradlew jlink ausführen, Fertig.
 

dzim

Top Contributor
So. Also um mal kurz zu demonstrieren, was ich mal auf Arbeit probiert habe:
  • Maven pom vom simpelsten Artifact erstellt (war auf Java 1.7, ohne JFX)
  • alles integriert, was ich brauchte (JFX Dependencies, Kotlin, Properties alles auf jeweils Version 11 und 12 getestet)
  • maven wrapper erstellt, simple Kotlin-Main erstellt
  • Kotlin-Main zu simpler FX-App umgestaltet
  • alles modularisiert (also module-info.java eingefügt und dem Modul einen grandiosen Namen gegeben)
  • zwischendurch alle Resources festgehalten, die mir so unterkamen und eine README geschrieben :D
  • Kotlin-Dependencies für Modularität aufgeräumt (das war fast noch das ekligste)
  • mit dem OpenJFX-Maven-Plugin custom images erstellt
  • den Early Access jpackager geholt und auf der CLI eine eigenständig lauffähige version (wie früher mit dem javapackager) erstellt, die aber nun auf dem zuvor via jlink (das macht das OpenJFX-Maven-Plugin) erstellten runtime image basiert
  • gefreut, als alles lief!
pom.xml
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>mycompany.jfx.test</groupId>
    <artifactId>package-test</artifactId>
    <version>0.0.1</version>

    <name>package-test</name>
    <description>JavaFX application to test packaging with.</description>

    <url>https://www.mycompany.ch</url>

    <scm>
        <connection>scm:git:git@git.mycompany.ch:dzimmermann/jfx-package-test.git</connection>
    </scm>

    <organization>
        <name>mycompany</name>
        <url>https://www.mycompany.ch</url>
    </organization>

    <licenses>
        <license>
            <name>Proprietary</name>
            <url>https://www.mycompany.ch</url>
            <distribution>repo</distribution>
        </license>
    </licenses>

    <developers>
        <developer>
            <id>dzim</id>
            <name>dzim</name>
            <email>dzim@mycompany.ch</email>
        </developer>
    </developers>

    <repositories>
        <repository>
            <id>maven</id>
            <url>http://repo1.maven.org/maven2</url>
        </repository>

        <repository>
            <id>jcenter</id>
            <url>https://jcenter.bintray.com/</url>
        </repository>
    </repositories>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <main.basedir>${basedir}</main.basedir>

        <use.java.version>12</use.java.version>
        <javafx.version>12.0.1</javafx.version>
        <kotlin.version>1.3.40</kotlin.version>

        <java.version>${use.java.version}</java.version>
        <maven.compile.java.version>${use.java.version}</maven.compile.java.version>
        <maven.compiler.source>${use.java.version}</maven.compiler.source>
        <maven.compiler.target>${use.java.version}</maven.compiler.target>

        <jackson.version>2.9.2</jackson.version>

        <app.main.class>mycompany.jfx.test.AppKt</app.main.class>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-base</artifactId>
            <version>${javafx.version}</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</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-media</artifactId>
            <version>${javafx.version}</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-web</artifactId>
            <version>${javafx.version}</version>
        </dependency>

        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib</artifactId>
            <version>${kotlin.version}</version>
            <classifier>modular</classifier>
            <exclusions>
                <exclusion>
                    <groupId>org.jetbrains.kotlin</groupId>
                    <artifactId>kotlin-stdlib-common</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.jetbrains</groupId>
                    <artifactId>annotations</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib-jdk7</artifactId>
            <version>${kotlin.version}</version>
            <classifier>modular</classifier>
            <exclusions>
                <exclusion>
                    <groupId>org.jetbrains.kotlin</groupId>
                    <artifactId>kotlin-stdlib</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib-jdk8</artifactId>
            <version>${kotlin.version}</version>
            <classifier>modular</classifier>
            <exclusions>
                <exclusion>
                    <groupId>org.jetbrains.kotlin</groupId>
                    <artifactId>kotlin-stdlib-jdk7</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.jetbrains.kotlin</groupId>
                    <artifactId>kotlin-stdlib</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-reflect</artifactId>
            <version>${kotlin.version}</version>
            <classifier>modular</classifier>
            <exclusions>
                <exclusion>
                    <groupId>org.jetbrains.kotlin</groupId>
                    <artifactId>kotlin-stdlib</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.module</groupId>
            <artifactId>jackson-module-kotlin</artifactId>
            <version>${jackson.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.jetbrains.kotlin</groupId>
                    <artifactId>kotlin-reflect</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.22.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>3.1.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-site-plugin</artifactId>
                    <version>3.7.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-project-info-reports-plugin</artifactId>
                    <version>3.0.0</version>
                </plugin>
            </plugins>
        </pluginManagement>

        <plugins>

            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>buildnumber-maven-plugin</artifactId>
                <version>1.4</version>
                <executions>
                    <execution>
                        <phase>validate</phase>
                        <goals>
                            <goal>create</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <release>${use.java.version}</release>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <inherited>true</inherited>
                <configuration>
                    <archive>
                        <manifest>
                            <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                            <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
                            <addClasspath>true</addClasspath>
                        </manifest>
                        <manifestEntries>
                            <!-- custom entries -->
                            <Specification-Vendor>${project.organization.name}</Specification-Vendor>
                            <Specification-Version>${project.version}</Specification-Version>
                            <Specification-Title>${project.name}</Specification-Title>
                            <Implementation-Vendor>${project.organization.name}</Implementation-Vendor>
                            <Implementation-Version>${project.version}-${buildNumber}</Implementation-Version>
                            <Implementation-Title>${project.name}</Implementation-Title>
                            <!-- <Automatic-Module-Name>${project.groupId}.${project.artifactId}</Automatic-Module-Name> -->
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>

            <plugin>
                <artifactId>kotlin-maven-plugin</artifactId>
                <groupId>org.jetbrains.kotlin</groupId>
                <version>${kotlin.version}</version>
                <configuration>
                    <!-- <compilerPlugins><plugin>spring</plugin></compilerPlugins> -->
                    <jvmTarget>${use.java.version}</jvmTarget> <!-- 1.8 -->
                </configuration>
                <executions>
                    <execution>
                        <id>compile</id>
                        <phase>process-sources</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                        <configuration>
                            <sourceDirs>
                                <sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
                                <sourceDir>${project.basedir}/src/main/java</sourceDir>
                            </sourceDirs>
                        </configuration>
                    </execution>
                    <execution>
                        <id>test-compile</id>
                        <goals>
                            <goal>test-compile</goal>
                        </goals>
                        <configuration>
                            <sourceDirs>
                                <sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
                                <sourceDir>${project.basedir}/src/test/java</sourceDir>
                            </sourceDirs>
                        </configuration>
                    </execution>
                </executions>
                <dependencies>
                    <!-- <dependency><groupId>org.jetbrains.kotlin</groupId><artifactId>kotlin-maven-allopen</artifactId><version>${kotlin.version}</version></dependency> -->
                </dependencies>
            </plugin>

            <plugin>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-maven-plugin</artifactId>
                <version>0.0.2</version>
                <configuration>
                    <!-- javafx:compile options -->
                    <source>${use.java.version}</source>
                    <target>${use.java.version}</target>
                    <release>${use.java.version}</release>
                    <mainClass>${app.main.class}</mainClass><!-- packagetest -->
                    <!-- javafx:jlink options -->
                    <jlinkImageName>${project.artifactId}</jlinkImageName>
                    <launcher>${project.artifactId}-launcher</launcher>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.6.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>java</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <mainClass>${app.main.class}</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

module-info.java
Java:
module packagetest {
    requires javafx.base;
    requires javafx.controls;
    requires javafx.graphics;
    requires kotlin.stdlib.jdk8;
    opens mycompany.jfx.test to javafx.fxml;
    exports mycompany.jfx.test;
}

App.kt
Java:
package mycompany.jfx.test

import javafx.application.Application
import javafx.scene.Scene
import javafx.scene.layout.BorderPane
import javafx.scene.layout.Priority
import javafx.stage.Stage

import javafx.event.EventTarget
import javafx.geometry.Pos
import javafx.scene.Group
import javafx.scene.Node
import javafx.scene.Parent
import javafx.scene.control.*
import javafx.scene.layout.*
import java.lang.reflect.Method

/*
* Here we go...
* (In JVM bytecode, this will become the class file AppKt.class, because it's a top-level function.)
*/
fun main(args: Array<String>) {
    Application.launch(FXApp::class.java, *args)
}

/*
* This is the application. Obviously.
* As far as I recall you need to split the Main class from the application class to easily create modules.
* Or let it run as a classpath based app. I don't recall the the reason, but I like the style anyway.
* (In JVM bytecode, this will become FXApp.class)
*/
class FXApp : Application() {

    override fun start(primaryStage: Stage) {

        primaryStage.apply {

            minWidth = 640.0
            minHeight = 480.0

            title = "FX"

            scene = BorderPane().let {
                it.center = vbox {
                    region { vgrow = Priority.ALWAYS }
                    label("Hello World!")
                    region { vgrow = Priority.ALWAYS }
                }
                Scene(it, minWidth, minHeight)
            }
        }.show()
    }
}

/*
* The following is a simplified extract from the great TornadoFX library.
* I simply didn't want a too large dependency list, and the current stable build of Tornado is not yet Java 9+ ready.
* And I also don't need all its functionality, so just ignore it - it's just a playground.
*/

fun EventTarget.hbox(spacing: Number? = null, alignment: Pos? = null, op: HBox.() -> Unit = {}): HBox {
    val hbox = HBox()
    if (alignment != null) hbox.alignment = alignment
    if (spacing != null) hbox.spacing = spacing.toDouble()
    return opcr(this, hbox, op)
}

fun EventTarget.vbox(spacing: Number? = null, alignment: Pos? = null, op: VBox.() -> Unit = {}): VBox {
    val vbox = VBox()
    if (alignment != null) vbox.alignment = alignment
    if (spacing != null) vbox.spacing = spacing.toDouble()
    return opcr(this, vbox, op)
}

var Node.hgrow: Priority?
    get() = HBox.getHgrow(this)
    set(value) {
        HBox.setHgrow(this, value)
    }
var Node.vgrow: Priority?
    get() = VBox.getVgrow(this)
    set(value) {
        VBox.setVgrow(this, value)
    }

fun EventTarget.region(op: Region.() -> Unit = {}) = opcr(this, Region(), op)

fun EventTarget.label(text: String = "", graphic: Node? = null, op: Label.() -> Unit = {}) = Label(text).attachTo(this, op) {
    if (graphic != null) it.graphic = graphic
}

inline fun <T : Node> opcr(parent: EventTarget, node: T, op: T.() -> Unit = {}) = node.apply {
    parent.addChildIfPossible(this)
    op(this)
}

inline fun <T : Node> T.attachTo(parent: EventTarget, op: T.() -> Unit = {}): T = opcr(parent, this, op)

internal inline fun <T : Node> T.attachTo(
        parent: EventTarget,
        after: T.() -> Unit,
        before: (T) -> Unit
) = this.also(before).attachTo(parent, after)

fun EventTarget.getChildList(): MutableList<Node>? = when (this) {
    is SplitPane -> items
    is ToolBar -> items
    is Pane -> children
    is Group -> children
    is HBox -> children
    is VBox -> children
    is Control -> (skin as? SkinBase<*>)?.children ?: getChildrenReflectively()
    is Parent -> getChildrenReflectively()
    else -> null
}

@Suppress("UNCHECKED_CAST", "PLATFORM_CLASS_MAPPED_TO_KOTLIN")
private fun Parent.getChildrenReflectively(): MutableList<Node>? {
    val getter = this.javaClass.findMethodByName("getChildren")
    if (getter != null && java.util.List::class.java.isAssignableFrom(getter.returnType)) {
        getter.isAccessible = true
        return getter.invoke(this) as MutableList<Node>
    }
    return null
}

fun Class<*>.findMethodByName(name: String): Method? {
    val method = (declaredMethods + methods).find { it.name == name }
    if (method != null) return method
    @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
    if (superclass == java.lang.Object::class.java) return null
    return superclass.findMethodByName(name)
}

@Suppress("UNNECESSARY_SAFE_CALL")
fun EventTarget.addChildIfPossible(node: Node, index: Int? = null) {

    if (this is Node) {
        // empty on purpose
    }
    when (this) {
        is ScrollPane -> content = node
        is Tab -> {
            content = node
        }
        is ButtonBase -> {
            graphic = node
        }
        is BorderPane -> {
        }
        is TabPane -> {
            val tab = Tab(node.toString(), node)
            tabs.add(tab)
        }
        is TitledPane -> {
            when (content) {
                is Pane -> content.addChildIfPossible(node, index)
                is Node -> {
                    val container = VBox()
                    container.children.addAll(content, node)
                    content = container
                }
                else -> content = node
            }
        }
        is CustomMenuItem -> {
            content = node
        }
        is MenuItem -> {
            graphic = node
        }
        else -> getChildList()?.apply {
            if (!contains(node)) {
                if (index != null && index < size)
                    add(index, node)
                else
                    add(node)
            }
        }
    }
}

README.md
Markdown:
# About this project

Test project, to experiment with AdoptOpenJDK, OpenJFX, Maven & `javafx-maven-plugin` to create a `jlink`ed application.

# Resources

* alternative OpenJDK build with OpenJFX already bundled into it: [ZuluFX][1]
* *GluonHQ*'s news about the `Gradle` and `Maven` plugins: [Plugins to ease the work with JavaFX 11+][2]
  * [openjfx.io][3] documentation for [Maven][4]
  * The source for `javafx-maven-plugin` on [GitHub][5]
* [Discussion][6] about Kotlin and its support for the `JPMS` (Java module system)
  * Examples for both `Gradle` and `Maven` for modules on [GitHub][7]

# Tasks

- [ ] **Linux**
    - [x] AdoptOpenJDK 11, OpenJFX 11
    - [x] AdoptOpenJDK 12, OpenJFX 12
    - [ ] AdoptOpenJDK 13, OpenJFX 13

- [ ] **Windows**
    - [x] AdoptOpenJDK 11, OpenJFX 11 (64Bit)
    - [x] AdoptOpenJDK 12, OpenJFX 12 (64Bit)
    - [ ] AdoptOpenJDK 13, OpenJFX 13 (64Bit)

# Packaging

Currently the packaging consist only of a tailored JRE with the applications module (and its dependencies) in it.
We could improve on that by using the backported `jpackage` application in pre-Java-13 versions.

See [here][8] and [here][9] for more information about the topic.

# NOTES

##### Build process
On Windows with another Java already installed, execute the `Maven` goal `javafx:[compile|run|jlink]` with an explicitly set `JAVA_HOME` environment
variable.
Otherwise the one where your profile or system points to might make the maven goal fail.

**Example:**
```batch
set JAVA_HOME=<path-to-adoptOpenJdk>
mvnw.cmd javafx:jlink
```

##### `jlink`ed Application

The launcher Batch file in your `jlink` build may contain a launcher (dependent on your `javafx-maven-plugin`, check the [documentation][5] for more info),
will use the `bin\java` while it probably should use `bin\javaw`.
To launch a Batch file seems ugly, so we should probably package the result with another tool, like `jpackage` (see section [Packaging](#packaging)).

##### `jpackage`d Application

To create a `jpackage` build, you need to download the tool from the links above.

**Procedure (works on both Linux & Windows):**
* build tool with `jlink` (via `javafx-maven-plugin`)
* change directory and go to the `target` dir
* verify, that the runtime image is present (this example uses the `artifacId` for its name - `package-test`)
* execute the following command
    ```bash
    ~/path-to-jpackage-build/bin/jpackage -o <targetDir> -n <appName> -m <moduleName>/<main-class> --runtime-image <jlinkImageName>
    ```

[1]: https://www.azul.com/downloads/zulu/zulufx/
[2]: https://gluonhq.com/plugins-to-ease-the-work-with-javafx-11/
[3]: https://openjfx.io/
[4]: https://openjfx.io/openjfx-docs/#maven
[5]: https://github.com/openjfx/javafx-maven-plugin/
[6]: https://discuss.kotlinlang.org/t/kotlin-support-for-java-9-module-system/2499/25
[7]: https://github.com/ilya-g/kotlin-jlink-examples
[8]: http://mail.openjdk.java.net/pipermail/openjfx-dev/2018-September/022500.html
[9]: https://jdk.java.net/jpackage/
[10]: https://github.com/agilhard-oss/jlink-jpackager-maven-plugin
[11]: https://github.com/agilhard-oss/jpackager-maven-example

P.S.: Hat sich irgendwer eigentlich mal die Übersetzungen im Code-Einfüge-Fenster vom Editor angesehen?
Markdown wird zu Abschrift (GitHub aromatisiert), und Swift zu Mauersegler... Ich ROFLe gerade hart. Innerlich! :D:D:D
 

dzim

Top Contributor
Hab es übrigens gerade mal auf Java & FX 13 ausprobiert. Nur eine Anpassung nötig: Kotlin muss explizit auf dem JVM-Target 12 bleiben, weil sie 13 (noch) nicht unterstützen.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
MiMa Fonts, Icons, Bilder in JavaFX Anwendung AWT, Swing, JavaFX & SWT 5
I JavaFX JavaFx-Anwendung für die Erstellung einer Windows-Anwendung? AWT, Swing, JavaFX & SWT 6
P Swing Anwendung von LayeredPanel AWT, Swing, JavaFX & SWT 6
J Netbeans die JavaFX-Anwendung wird nicht ausgeführt AWT, Swing, JavaFX & SWT 16
tommybalbor JavaFx Anwendung klappt nicht für macOs Nutzern, wenn ich zwei dependecies bei maven hinzufüge AWT, Swing, JavaFX & SWT 6
thor_norsk JavaFX Anwendung stürzt ab AWT, Swing, JavaFX & SWT 4
H Fehler: Zum Ausführen dieser Anwendung benötigte JavaFX-Runtime-Komponenten fehlen AWT, Swing, JavaFX & SWT 44
G JavaFX Steuerung bzw. Test von externer JavaFX Anwendung (liegt nur als jar vor) AWT, Swing, JavaFX & SWT 9
N JavaFX Vor beenden der Anwendung durch klicken von X Dialog zeigen AWT, Swing, JavaFX & SWT 1
beli3ver JavaFX Anwendung startet nicht, kann den Fehler nicht finden (Exception in Application start method) AWT, Swing, JavaFX & SWT 1
B JavaFX Wie A4-Seite in meiner Anwendung repräsentieren AWT, Swing, JavaFX & SWT 6
B JavaFX JavaFX Anwendung deployen (entw als runnableJAR oder exe-Datei) AWT, Swing, JavaFX & SWT 15
OSchriever Anwendung aus SystemTray öffnen AWT, Swing, JavaFX & SWT 29
G JavaFX SplitPane Anwendung - Controller Probleme AWT, Swing, JavaFX & SWT 5
T Anwendung mit X schliessen AWT, Swing, JavaFX & SWT 1
D PDF Viewer in SWT-Anwendung AWT, Swing, JavaFX & SWT 8
O Basics - Anwendung erstellen mit mehreren Szenen AWT, Swing, JavaFX & SWT 1
G JavaFX JavaFX-Dialog aus einer Nicht-JavaFX-Anwendung heraus AWT, Swing, JavaFX & SWT 1
A JavaFX Anwendung in Jar Datei AWT, Swing, JavaFX & SWT 8
D Swing Anwendung ohne JPanel erstellen AWT, Swing, JavaFX & SWT 1
J Splashscreen Start Anwendung AWT, Swing, JavaFX & SWT 14
MiMa Programmeinstellungen für Anwendung?? AWT, Swing, JavaFX & SWT 54
L JavaFX LoadException beim Laden von JavaFX Anwendung AWT, Swing, JavaFX & SWT 6
I JFileChooser mit System L&F bei anderem L&F der eigtl. Anwendung AWT, Swing, JavaFX & SWT 0
Blender3D Meine Swing Anwendung läuft unter Windows 10 und Ubuntu aber nicht auf Windows 7 AWT, Swing, JavaFX & SWT 16
L JavaFX PdfViewer für JavaFX Anwendung AWT, Swing, JavaFX & SWT 6
D JafaFX Anwendung beenden AWT, Swing, JavaFX & SWT 11
B Wie erstelle ich eine JavaFX Anwendung von diesem Code? AWT, Swing, JavaFX & SWT 3
javampir Swing repaint in JavaFX Anwendung AWT, Swing, JavaFX & SWT 3
X Anwendung skalierbar AWT, Swing, JavaFX & SWT 3
D JavaFX Erkennen wenn eine Anwendung geschlossen wird und etwas tun? AWT, Swing, JavaFX & SWT 4
D JavaFX Anwendung hängt sich permanent auf AWT, Swing, JavaFX & SWT 6
L JavaFX Java FX Anwendung nach MVC mit Observer Pattern AWT, Swing, JavaFX & SWT 15
X Swing Anwendung regaiert auf keine Buttons mehr wärend while(scanner.hasNextLine()) ausgeführt wird. AWT, Swing, JavaFX & SWT 4
I Variabeln speichern in Desktop Anwendung AWT, Swing, JavaFX & SWT 2
V Anwendung im Vollbild zentrieren AWT, Swing, JavaFX & SWT 13
A Swing Textübergabe innerhalb der Anwendung in unterschiedlichen Fenster AWT, Swing, JavaFX & SWT 8
GreyFox JLabel in laufender Anwendung erzeugen AWT, Swing, JavaFX & SWT 6
J JavaFX Anwendung läuft in eclipse, nicht aber exportiert AWT, Swing, JavaFX & SWT 2
P Anwendung kommt nach minimieren nicht mehr in den Vordergrund AWT, Swing, JavaFX & SWT 5
K 3D-Grafik Anwendung von Java in Gnuplot AWT, Swing, JavaFX & SWT 3
M SWT Anwendung in der Symbolleiste verstecken AWT, Swing, JavaFX & SWT 5
B SWT Redesign SWT Anwendung AWT, Swing, JavaFX & SWT 7
M Java anwendung VOR vollbildspielen (schon wieder...) AWT, Swing, JavaFX & SWT 5
S Swing Lauftext Performance Probleme, in größerer Anwendung AWT, Swing, JavaFX & SWT 6
VfL_Freak Swing Zweiter Monitor von Java-Anwendung ansprechbar ?? AWT, Swing, JavaFX & SWT 2
S Swing Ist meine gute Java Anwendung vorgängig? AWT, Swing, JavaFX & SWT 20
P Klassenaufbau bei komplexerer GUI Anwendung AWT, Swing, JavaFX & SWT 14
S Java GUI Anwendung ohne Konsole starten AWT, Swing, JavaFX & SWT 6
qwerqer Swing Anwendung soll blinken (Taskleiste) AWT, Swing, JavaFX & SWT 3
R Java Desktop Anwendung erstellen. Womit? AWT, Swing, JavaFX & SWT 3
eLogic Fullscreen anwendung aus der man nicht rauskommt AWT, Swing, JavaFX & SWT 37
T Java-Anwendung arbeitet Programm in seltsamer Reihenfolge ab AWT, Swing, JavaFX & SWT 3
H Anwendung schließen ohne System.exit AWT, Swing, JavaFX & SWT 5
R Anwendung ohne Symbol in der Taskleiste AWT, Swing, JavaFX & SWT 3
H SWT RAP Anwendung - Tabelle - Theming AWT, Swing, JavaFX & SWT 3
alderwaran Swing XML editor plugin für eigene anwendung AWT, Swing, JavaFX & SWT 2
G Swing Update-Funktion für Swing-Anwendung AWT, Swing, JavaFX & SWT 5
C Swing Eine SWING-Anwendung mittels MVC AWT, Swing, JavaFX & SWT 4
Eldorado Frage zur Anwendung des MVC-Konzept AWT, Swing, JavaFX & SWT 33
B SWT Hello World-Anwendung mit GUI in Eclipse -Problem mit Import von SWT AWT, Swing, JavaFX & SWT 9
G Applet und Swing Anwendung AWT, Swing, JavaFX & SWT 2
J Client Server Anwendung - Mehrere Clients in einer Server GUI AWT, Swing, JavaFX & SWT 11
F Anwendung auf Teskleiste legen AWT, Swing, JavaFX & SWT 3
B MDI Anwendung alle maximierten InternalFrames in Tabs AWT, Swing, JavaFX & SWT 3
T Anwendung starten AWT, Swing, JavaFX & SWT 5
J Anwendung von Swing nach SWT bzw. Eclipse portieren AWT, Swing, JavaFX & SWT 3
2 Tablet-PC Java-Anwendung -> Tablet-Pen Problem !! AWT, Swing, JavaFX & SWT 3
J Swing Anwendung schließen im Listener AWT, Swing, JavaFX & SWT 3
isowiz Vorteil einer RCP Anwendung gegenüber Swing AWT, Swing, JavaFX & SWT 3
? Java-SWT-Anwendung in der Taskleiste nicht sichtbar AWT, Swing, JavaFX & SWT 6
H Netbeans-Anwendung schliessen AWT, Swing, JavaFX & SWT 8
M "Billig Excel" Anwendung mit Swing - Aufwand ? AWT, Swing, JavaFX & SWT 4
G "Views-Abwechseln-Pro " in RCP-Anwendung AWT, Swing, JavaFX & SWT 2
H PopUp-Fenster in einer Java Server Faces Anwendung AWT, Swing, JavaFX & SWT 4
T Auf Fenster innerhalb der Anwendung zugreifen-auch elegant? AWT, Swing, JavaFX & SWT 2
G Organisation Anwendung mit mehreren Eingabedialogen AWT, Swing, JavaFX & SWT 3
H JWindow schließen bei einem Klick außerhalb der Anwendung? AWT, Swing, JavaFX & SWT 19
G SWT DatePicker funzt nicht in eigener Anwendung AWT, Swing, JavaFX & SWT 5
E Bestehende Anwendung erweitern ->JFrame in JPanel verpack AWT, Swing, JavaFX & SWT 4
U Anwendung nicht beenden beim form schliessen? AWT, Swing, JavaFX & SWT 6
T "Echte" MDI Anwendung AWT, Swing, JavaFX & SWT 4
G Auf markierten Text einer anderen Anwendung zugreifen. AWT, Swing, JavaFX & SWT 8
G Relativer Pfad in Rich Client Anwendung AWT, Swing, JavaFX & SWT 4
N Keyboard-Shortcut, der in der ganzen Anwendung funktioniert AWT, Swing, JavaFX & SWT 2
D JDIC Browser in SWT/JFace Anwendung nutzen AWT, Swing, JavaFX & SWT 2
J Swing-Anwendung mit ActionListener AWT, Swing, JavaFX & SWT 7
S Anwendung über Button beenden? AWT, Swing, JavaFX & SWT 4
O Anwendung aus dem Programm heraus neu starten AWT, Swing, JavaFX & SWT 2
U Anwendung mit mehreren "Fenstern" AWT, Swing, JavaFX & SWT 4
R Screenshot von fremder Anwendung AWT, Swing, JavaFX & SWT 4
Hotkey Freie Icons für Anwendung mit Java Look&Feel AWT, Swing, JavaFX & SWT 4
S SWT-Anwendung als startfähiges Jar unter Linux AWT, Swing, JavaFX & SWT 4
P GUI geschickt von dem Rest der Anwendung trennen AWT, Swing, JavaFX & SWT 6
S HTML-Datei in Anwendung (JEditorPane) AWT, Swing, JavaFX & SWT 5
A Screenshot einer Anwendung erstellen AWT, Swing, JavaFX & SWT 14
A MVC-Pattern - Kreuzweise Anwendung? AWT, Swing, JavaFX & SWT 4
M Komponenten einer Anwendung in JTree strukturiert auflisten? AWT, Swing, JavaFX & SWT 4
G Anwendung um Scrollpane erweitern AWT, Swing, JavaFX & SWT 2
A Look and Feel einer Anwendung verändern AWT, Swing, JavaFX & SWT 7

Ähnliche Java Themen

Neue Themen


Oben