JavaFX OpenJFX, SpringBoot und Gradle

Hallo zusammen,

hat jemand von euch schon eine fertige Konfiguration für OpenJFX11-14 mit SpringBoot in Gradle konfiguriert bekommen?

Ich habe die Gradle Datei von diesem Projekt angepasst und SpringBoot dependencies ergänzt
https://github.com/openjfx/samples/tree/master/HelloFX/Gradle

Danach bekomme ich compile error für JavaFX dependencies.

Vielleicht hat das jemand schon parat und kann es mit mir teilen.

Vielen Dank
lam

P.S. Dzim du hast sowas bestimmt oder :)
 
Zuletzt bearbeitet:
Warte mal... Mir ist da kürzlich ein Beispiel untergekommen:
https://blog.jetbrains.com/idea/2019/12/tutorial-reactive-spring-boot/

Konkreter hier:
https://blog.jetbrains.com/idea/2019/11/tutorial-reactive-spring-boot-a-javafx-spring-boot-application/
-> https://github.com/trishagee/jb-stock-client/tree/master/stock-ui
-> https://github.com/trishagee/jb-stock-client/blob/master/stock-ui/pom.xml

Code:
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.mechanitis</groupId>
    <artifactId>stock-ui</artifactId>
    <version>0.0.2-SNAPSHOT</version>
    <name>stock-ui</name>
    <description>JavaFX front-end for the stock prices application</description>

    <properties>
        <java.version>11</java.version>
        <javafx.version>13.0.1</javafx.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <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>com.mechanitis</groupId>
            <artifactId>stock-client</artifactId>
            <version>0.0.2-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
Du brauchst weder <artifactId>reactor-test</artifactId> (es sei denn, du möchtest den Reactive ReST Client von Spring Boot verwenden) noch <artifactId>stock-client</artifactId> (der ist spezifisch für das Beispiel hier).

War es das, was du suchtest?

PS: Nutze bitte das nächste Mal das @-Handle, dann bekomme ich auch eine Nachricht. ;) @lam_tr
 
Ich konnte es kaum erwarten und habe meine Mittagspause dafür vergnügt. Jetzt habe ich es mit Gradle hinbekommen, echt klasse.

@dzim wenn wir schon dabei sind, hast du auch schon Erfahrung mit Graalvm and OpenJFX. Ich habe einiges gelesen, aber dieses Ganze wie man das so konfiguriert, finde ich so schlecht.
 
Meine bisherige Erfahrung damit ist: Ich habe es in meinem Übungsprojekt leider nicht zum kompilieren bekommen... :rolleyes:
(Und ich möchte explizit dieses nutzen. Sonst habe ich ja kaum einen Lerneffekt.)

Wenn ich mal wieder etwas mehr Zeit zum "basteln" habe, werde ich es noch einmal probieren.
 
Moin @dzim ,

wenn ich die Anwendung mit JLink bauen möchte, bekomme ich diese Fehlermeldung

Code:
C:\Users\...\build\jlinkbase\tmpjars\de.dc.merged.module\module-info.java:1370: error: package com.fasterxml.jackson does not exist
    uses com.fasterxml.jackson.core;
                              ^
C:\Users\...\build\jlinkbase\tmpjars\de.dc.merged.module\module-info.java:1371: error: package com.fasterxml does not exist
    uses com.fasterxml.classmate;
                      ^
C:\Users\...\build\jlinkbase\tmpjars\de.dc.merged.module\module-info.java:1372: error: package com.fasterxml.jackson does not exist
    uses com.fasterxml.jackson.databind;
                              ^
C:\Users\...\build\jlinkbase\tmpjars\de.dc.merged.module\module-info.java:1373: error: package com.fasterxml.jackson.module does not exist
    uses com.fasterxml.jackson.module.paramnames;
                                     ^
C:\Users\...\build\jlinkbase\tmpjars\de.dc.merged.module\module-info.java:1374: error: package com.fasterxml.jackson does not exist
    uses com.fasterxml.jackson.annotation;
                              ^
C:\Users\...\build\jlinkbase\tmpjars\de.dc.merged.module\module-info.java:1375: error: package javafx does not exist
    uses javafx.base;
               ^
C:\Users\...\build\jlinkbase\tmpjars\de.dc.merged.module\module-info.java:1423: error: the service implementation type must be a subtype of the service interface type, or have a public static no-args method named "provider" returning the service implementation
    provides javax.xml.bind.JAXBContext with com.sun.xml.bind.v2.ContextFactory;
                                                                ^
C:\Users\...\build\jlinkbase\tmpjars\de.dc.merged.module\module-info.java:1437: error: package javax.enterprise.inject.spi does not exist
    provides javax.enterprise.inject.spi.Extension with org.springframework.data.jpa.repository.cdi.JpaRepositoryExtension;
                                        ^
C:\Users\...\build\jlinkbase\tmpjars\de.dc.merged.module\module-info.java:1512: error: package org.apache.logging.log4j.spi is not visible
    provides org.apache.logging.log4j.spi.Provider with org.apache.logging.slf4j.SLF4JProvider;
Ich habe dann den Gradle Task suggestMergedModuleInfo ausgeührt um alle required dependencies zu bekommen. Im Anschluss habe ich die build.gradle file erweitert mit

Code:
jlink {
    mergedModule {
        requires 'com.fasterxml.jackson.core';
        requires 'com.fasterxml.classmate';
        requires 'com.fasterxml.jackson.databind';
        requires 'com.fasterxml.jackson.module.paramnames';
        requires 'com.fasterxml.jackson.annotation';
        requires 'javafx.base';
    }
    launcher {
        name = 'exe_name'
    }
}
scheint leider immer noch nicht zu gehen, hier wird ein ähnliches Problem geschildert https://github.com/beryx/badass-jlink-plugin/issues/59 . Leider komme ich da nicht weiter.

Kennst du einen Weg um das zu Lösen?

Viele Grüße
lam
 
Wie sieht denn deine generierte module-info.java aus? Hast du zusätzlich auch eine manuell erstellte? Wenn ja, wo liegt sie (src/main/[java|kotlin|...])
Meine manuell erstellte sieht so aus:
Java:
module packagetest {

    requires javafx.base;
    requires javafx.controls;
    requires javafx.graphics;

    requires kotlin.stdlib.jdk8;

    opens ch.cnlab.jfx.test to javafx.fxml;

    exports ch.cnlab.jfx.test;
}
 
Btw: Ich habe heute mit etwas Support durch Gluon den Build der Test-App mittels GraalVM hinbekommen! :D

0.3s gegen 2.1s Zeit zum Aufstarten können sich schon sehen lassen! Ist halt nen 50 MB Executable (unter Linux). Braucht aber auch nur genausoviel Speicher!
 
Wie sieht denn deine generierte module-info.java aus? Hast du zusätzlich auch eine manuell erstellte? Wenn ja, wo liegt sie (src/main/[java|kotlin|...])
Meine manuell erstellte sieht so aus:
Java:
module packagetest {

    requires javafx.base;
    requires javafx.controls;
    requires javafx.graphics;

    requires kotlin.stdlib.jdk8;

    opens ch.cnlab.jfx.test to javafx.fxml;

    exports ch.cnlab.jfx.test;
}
Ich habs zwar Kenntnisse in OSGI Modulaisierung aber mit Java Modularisierung, kenne ich mich noch überhaupt nicht. Ich habe über Gradle Skript eine automatisch erstelle Liste bekommen, die sieht auch sehr lang aus. Ich habe einmal nur Jackson Abhängigkeiten genommen und einmal komplett, bei beidem knalle ich voll auf die oben erwähnte Fehlermeldung.

Das ist die vollständige generierte module-info.java
Code:
mergedModule {
    requires 'com.fasterxml.jackson.core';
    requires 'com.fasterxml.classmate';
    requires 'com.fasterxml.jackson.databind';
    requires 'com.fasterxml.jackson.module.paramnames';
    requires 'java.xml';
    requires 'com.sun.xml.txw2';
    requires 'java.desktop';
    requires 'javafx.base';
    requires 'jdk.unsupported';
    requires 'java.management';
    requires 'java.naming';
    requires 'java.security.sasl';
    requires 'com.sun.xml.fastinfoset';
    requires 'java.instrument';
    requires 'com.fasterxml.jackson.annotation';
    requires 'java.logging';
    requires 'jdk.httpserver';
    requires 'java.sql';
    requires 'java.prefs';
    requires 'jdk.jdi';
    requires 'java.rmi';
    requires 'java.security.jgss';
    requires 'jdk.attach';
    requires 'java.scripting';
    requires 'java.datatransfer';
    requires 'java.compiler';
    requires 'java.management.rmi';
    requires 'java.sql.rowset';
    requires 'java.transaction.xa';
    uses 'javax.mail.Provider';
    uses 'org.jboss.logging.LoggerProvider';
    uses 'net.fortuna.ical4j.transform.rfc5545.Rfc5545PropertyRule';
    uses 'org.apache.juli.logging.Log';
    uses 'javax.persistence.spi.PersistenceProvider';
    uses 'org.apache.tomcat.websocket.Authenticator';
    uses 'javax.validation.spi.ValidationProvider';
    uses 'javax.websocket.server.ServerEndpointConfig.Configurator';
    uses 'javax.websocket.ContainerProvider';
    uses 'net.fortuna.ical4j.transform.rfc5545.Rfc5545ComponentRule';
    provides 'net.fortuna.ical4j.model.ParameterFactory' with 'net.fortuna.ical4j.model.parameter.Abbrev.Factory',
                'net.fortuna.ical4j.model.parameter.AltRep.Factory',
                'net.fortuna.ical4j.model.parameter.Cn.Factory',
                'net.fortuna.ical4j.model.parameter.CuType.Factory',
                'net.fortuna.ical4j.model.parameter.DelegatedFrom.Factory',
                'net.fortuna.ical4j.model.parameter.Dir.Factory',
                'net.fortuna.ical4j.model.parameter.Display.Factory',
                'net.fortuna.ical4j.model.parameter.Email.Factory',
                'net.fortuna.ical4j.model.parameter.Encoding.Factory',
                'net.fortuna.ical4j.model.parameter.FbType.Factory',
                'net.fortuna.ical4j.model.parameter.Feature.Factory',
                'net.fortuna.ical4j.model.parameter.FmtType.Factory',
                'net.fortuna.ical4j.model.parameter.Label.Factory',
                'net.fortuna.ical4j.model.parameter.Language.Factory',
                'net.fortuna.ical4j.model.parameter.Member.Factory',
                'net.fortuna.ical4j.model.parameter.PartStat.Factory',
                'net.fortuna.ical4j.model.parameter.Range.Factory',
                'net.fortuna.ical4j.model.parameter.RelType.Factory',
                'net.fortuna.ical4j.model.parameter.Related.Factory',
                'net.fortuna.ical4j.model.parameter.Role.Factory',
                'net.fortuna.ical4j.model.parameter.Rsvp.Factory',
                'net.fortuna.ical4j.model.parameter.ScheduleAgent.Factory',
                'net.fortuna.ical4j.model.parameter.ScheduleStatus.Factory',
                'net.fortuna.ical4j.model.parameter.SentBy.Factory',
                'net.fortuna.ical4j.model.parameter.Type.Factory',
                'net.fortuna.ical4j.model.parameter.TzId.Factory',
                'net.fortuna.ical4j.model.parameter.Value.Factory',
                'net.fortuna.ical4j.model.parameter.Vvenue.Factory';
    provides 'net.fortuna.ical4j.transform.rfc5545.Rfc5545ComponentRule' with 'net.fortuna.ical4j.transform.rfc5545.VAlarmRule',
                'net.fortuna.ical4j.transform.rfc5545.VEventRule';
    provides 'org.apache.commons.logging.LogFactory' with 'org.apache.commons.logging.LogFactoryService';
    provides 'net.fortuna.ical4j.transform.rfc5545.Rfc5545PropertyRule' with 'net.fortuna.ical4j.transform.rfc5545.AttendeePropertyRule',
                'net.fortuna.ical4j.transform.rfc5545.CreatedPropertyRule',
                'net.fortuna.ical4j.transform.rfc5545.DTStampRule',
                'net.fortuna.ical4j.transform.rfc5545.DateListPropertyRule',
                'net.fortuna.ical4j.transform.rfc5545.DatePropertyRule',
                'net.fortuna.ical4j.transform.rfc5545.TzIdRule';
    provides 'javax.xml.bind.JAXBContext' with 'com.sun.xml.bind.v2.ContextFactory';
    provides 'javax.persistence.spi.PersistenceProvider' with 'org.hibernate.jpa.HibernatePersistenceProvider';
    provides 'java.sql.Driver' with 'org.h2.Driver';
    provides 'javax.mail.Provider' with 'com.sun.mail.imap.IMAPProvider',
                'com.sun.mail.imap.IMAPSSLProvider',
                'com.sun.mail.pop3.POP3Provider',
                'com.sun.mail.pop3.POP3SSLProvider',
                'com.sun.mail.smtp.SMTPProvider',
                'com.sun.mail.smtp.SMTPSSLProvider';
    provides 'javax.servlet.ServletContainerInitializer' with 'org.apache.tomcat.websocket.server.WsSci';
    provides 'javax.websocket.server.ServerEndpointConfig.Configurator' with 'org.apache.tomcat.websocket.server.DefaultServerEndpointConfigurator';
    provides 'net.fortuna.ical4j.validate.CalendarValidatorFactory' with 'net.fortuna.ical4j.validate.DefaultCalendarValidatorFactory';
    provides 'javax.validation.spi.ValidationProvider' with 'org.hibernate.validator.HibernateValidator';
    provides 'javax.websocket.ContainerProvider' with 'org.apache.tomcat.websocket.WsContainerProvider';
    provides 'javax.enterprise.inject.spi.Extension' with 'org.springframework.data.jpa.repository.cdi.JpaRepositoryExtension';
    provides 'net.fortuna.ical4j.model.ComponentFactory' with 'net.fortuna.ical4j.model.component.Available.Factory',
                'net.fortuna.ical4j.model.component.Daylight.Factory',
                'net.fortuna.ical4j.model.component.Standard.Factory',
                'net.fortuna.ical4j.model.component.VAlarm.Factory',
                'net.fortuna.ical4j.model.component.VAvailability.Factory',
                'net.fortuna.ical4j.model.component.VEvent.Factory',
                'net.fortuna.ical4j.model.component.VFreeBusy.Factory',
                'net.fortuna.ical4j.model.component.VJournal.Factory',
                'net.fortuna.ical4j.model.component.VTimeZone.Factory',
                'net.fortuna.ical4j.model.component.VToDo.Factory',
                'net.fortuna.ical4j.model.component.VVenue.Factory';
    provides 'net.fortuna.ical4j.model.PropertyFactory' with 'net.fortuna.ical4j.model.property.Acknowledged.Factory',
                'net.fortuna.ical4j.model.property.Action.Factory',
                'net.fortuna.ical4j.model.property.Attach.Factory',
                'net.fortuna.ical4j.model.property.Attendee.Factory',
                'net.fortuna.ical4j.model.property.BusyType.Factory',
                'net.fortuna.ical4j.model.property.CalScale.Factory',
                'net.fortuna.ical4j.model.property.Categories.Factory',
                'net.fortuna.ical4j.model.property.Clazz.Factory',
                'net.fortuna.ical4j.model.property.Color.Factory',
                'net.fortuna.ical4j.model.property.Comment.Factory',
                'net.fortuna.ical4j.model.property.Completed.Factory',
                'net.fortuna.ical4j.model.property.Conference.Factory',
                'net.fortuna.ical4j.model.property.Contact.Factory',
                'net.fortuna.ical4j.model.property.Country.Factory',
                'net.fortuna.ical4j.model.property.Created.Factory',
                'net.fortuna.ical4j.model.property.Description.Factory',
                'net.fortuna.ical4j.model.property.DtEnd.Factory',
                'net.fortuna.ical4j.model.property.DtStamp.Factory',
                'net.fortuna.ical4j.model.property.DtStart.Factory',
                'net.fortuna.ical4j.model.property.Due.Factory',
                'net.fortuna.ical4j.model.property.Duration.Factory',
                'net.fortuna.ical4j.model.property.ExDate.Factory',
                'net.fortuna.ical4j.model.property.ExRule.Factory',
                'net.fortuna.ical4j.model.property.ExtendedAddress.Factory',
                'net.fortuna.ical4j.model.property.FreeBusy.Factory',
                'net.fortuna.ical4j.model.property.Geo.Factory',
                'net.fortuna.ical4j.model.property.Image.Factory',
                'net.fortuna.ical4j.model.property.LastModified.Factory',
                'net.fortuna.ical4j.model.property.Locality.Factory',
                'net.fortuna.ical4j.model.property.Location.Factory',
                'net.fortuna.ical4j.model.property.LocationType.Factory',
                'net.fortuna.ical4j.model.property.Method.Factory',
                'net.fortuna.ical4j.model.property.Name.Factory',
                'net.fortuna.ical4j.model.property.Organizer.Factory',
                'net.fortuna.ical4j.model.property.PercentComplete.Factory',
                'net.fortuna.ical4j.model.property.Postalcode.Factory',
                'net.fortuna.ical4j.model.property.Priority.Factory',
                'net.fortuna.ical4j.model.property.ProdId.Factory',
                'net.fortuna.ical4j.model.property.RDate.Factory',
                'net.fortuna.ical4j.model.property.RRule.Factory',
                'net.fortuna.ical4j.model.property.RecurrenceId.Factory',
                'net.fortuna.ical4j.model.property.RefreshInterval.Factory',
                'net.fortuna.ical4j.model.property.Region.Factory',
                'net.fortuna.ical4j.model.property.RelatedTo.Factory',
                'net.fortuna.ical4j.model.property.Repeat.Factory',
                'net.fortuna.ical4j.model.property.RequestStatus.Factory',
                'net.fortuna.ical4j.model.property.Resources.Factory',
                'net.fortuna.ical4j.model.property.Sequence.Factory',
                'net.fortuna.ical4j.model.property.Source.Factory',
                'net.fortuna.ical4j.model.property.Status.Factory',
                'net.fortuna.ical4j.model.property.StreetAddress.Factory',
                'net.fortuna.ical4j.model.property.Summary.Factory',
                'net.fortuna.ical4j.model.property.Tel.Factory',
                'net.fortuna.ical4j.model.property.Transp.Factory',
                'net.fortuna.ical4j.model.property.Trigger.Factory',
                'net.fortuna.ical4j.model.property.TzId.Factory',
                'net.fortuna.ical4j.model.property.TzName.Factory',
                'net.fortuna.ical4j.model.property.TzOffsetFrom.Factory',
                'net.fortuna.ical4j.model.property.TzOffsetTo.Factory',
                'net.fortuna.ical4j.model.property.TzUrl.Factory',
                'net.fortuna.ical4j.model.property.Uid.Factory',
                'net.fortuna.ical4j.model.property.Url.Factory',
                'net.fortuna.ical4j.model.property.Version.Factory';
    provides 'org.apache.logging.log4j.spi.Provider' with 'org.apache.logging.slf4j.SLF4JProvider';
}
 
Das sieht irgendwie nicht richtig aus:
  • ich hab keine einfachen Anführungsstriche um die Module (oder angebotenen Service-Klassen)
  • ich hab nicht eine derart abstrus hohe Menge an provides drin
  • die Syntax ist doch module moduleName { /* content */ }
Sehr verwirrend.
 
Das sieht irgendwie nicht richtig aus:
  • ich hab keine einfachen Anführungsstriche um die Module (oder angebotenen Service-Klassen)
  • ich hab nicht eine derart abstrus hohe Menge an provides drin
  • die Syntax ist doch module moduleName { /* content */ }
Sehr verwirrend.
Axo ja ich habe vergessen zu erwähnen, ich habe kein modul-info.java. Die wird im Rahmen von jlink über den Gradle Task erstellt.

das oben in der Box ist eine Ergänzung für build.gradle im jlink{} Knoten.
 
Ok. Dann aber stellt sich die Frage: Wozu brauchst du so viel!?
Gerade die ganzen provides.

Ob generiert oder nicht: in deinen build oder out oder target Verzeichnis müssen ja die Class-Files herumliegen - da müsste dann auch eine java-module.class sein -> decompiler drüber laufen lassen (z.B. einfach Doppelklick mit IntelliJ) und den Inhalt anschauen.
Bist du ansonsten auch sicher, dass alle nötigen Dependencies auch wirklich da sind?
 
Passende Stellenanzeigen aus deiner Region:

Neue Themen

Oben