Desktop-Window in SpringBoot

ExceptionOfExpectation

Aktives Mitglied
Hallo,
ich hatte mir überlegt, wie ich eine Desktop-Application in SpringBoot starte. Entweder .javax.swing.JFrame oder javafx.application.Application, eine von beiden.

Zuerst habe ich mit javaFX versucht, dafür auch passende Dependency:

XML:
<dependency>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx</artifactId>
    <version>11</version>
    <type>pom</type>
</dependency>
Leider wurde es von Maven nicht erkannt, dann einfach mit Swing versucht. Daraufhin wurde mir folgende Fehlermeldung geworfen: java.awt.HeadlessException. Zuerst habe ich versucht es in der application.properties zuändern, wurde nicht erkannt, dann habe ich in main-Methode die Einstellungen konfiguriert:

Java:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;

import com.tutego.controller.ImageTransport;
import com.tutego.controller.MyListener;




@SpringBootApplication
@EnableCaching
public class Date4uAppApplication {

    public static void main(String[] args) {
        SpringApplicationBuilder builder = new SpringApplicationBuilder(Date4uAppApplication.class);
        builder.headless(false);
        ConfigurableApplicationContext context = builder.run(args);
        //SpringApplication.run(Date4uAppApplication.class, args);
    }
}
Und schon lief es problemlos, also alles wie ich es wollte. Nun meine zwei Fragen:
1. Wie bringe ich javaFX zum laufen?
2. Gibt es keine andere Möglichkeit die Property "headless" zuändern ohne es im Java-Code zu tun, einen eleganteren Weg?
 

KonradN

Super-Moderator
Mitarbeiter
Leider wurde es von Maven nicht erkannt,
Das liegt einfach daran, dass Du kein gültiges Artefact angegeben hast. Schau einfach auf mvnrepository.com, was es da an Artefakten gibt:
Maven Repository: org.openjfx (mvnrepository.com)
Du wirst da also etwas brauchen wie
XML:
<!-- https://mvnrepository.com/artifact/org.openjfx/javafx-graphics -->
<dependency>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-graphics</artifactId>
    <version>11.0.2</version>
</dependency>
wenn es die 11er Version sein soll.

Und wenn Der EDT Thread läuft, dann sollte es keine Probleme mehr geben. Also erst das Fenster erzeugen und dann die SpringBootApplication starten.

Kleines Beispiel:
Java:
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import javax.swing.*;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SwingUtilities.invokeLater( () -> {
            JFrame frame = new JFrame("Test");
            frame.setSize(500, 300);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            JButton button = new JButton("Test");
            frame.add(button);
            frame.setVisible(true);

            button.addActionListener( e -> {
                JOptionPane.showMessageDialog(frame, "Button clicked!");
            });

        });
        SpringApplication.run(DemoApplication.class, args);
    }

}

Sobald die Reihenfolge umgedreht wurde, ist die von Dir bereits genannte Fehlermeldung da.
 

KonradN

Super-Moderator
Mitarbeiter
Du kannst es auch erzwingen, in dem Du java.awt.headless=false setzt. (Als jvm Parameter mittels -D)

Das kannst du - wenn Du es über mvn spring-boot:run starten können willst, z.B. so setzen:
XML:
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <jvmArguments>-Djava.awt.headless=false</jvmArguments>
                </configuration>
            </plugin>

Oder halt als JVM Option in der Run Configuration eintragen.
 

ExceptionOfExpectation

Aktives Mitglied
Das liegt einfach daran, dass Du kein gültiges Artefact angegeben hast. Schau einfach auf mvnrepository.com, was es da an Artefakten gibt:
Maven Repository: org.openjfx (mvnrepository.com)
Du wirst da also etwas brauchen wie
XML:
<!-- https://mvnrepository.com/artifact/org.openjfx/javafx-graphics -->
<dependency>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-graphics</artifactId>
    <version>11.0.2</version>
</dependency>
wenn es die 11er Version sein soll.

Und wenn Der EDT Thread läuft, dann sollte es keine Probleme mehr geben. Also erst das Fenster erzeugen und dann die SpringBootApplication starten.

Kleines Beispiel:
Java:
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import javax.swing.*;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SwingUtilities.invokeLater( () -> {
            JFrame frame = new JFrame("Test");
            frame.setSize(500, 300);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            JButton button = new JButton("Test");
            frame.add(button);
            frame.setVisible(true);

            button.addActionListener( e -> {
                JOptionPane.showMessageDialog(frame, "Button clicked!");
            });

        });
        SpringApplication.run(DemoApplication.class, args);
    }

}

Sobald die Reihenfolge umgedreht wurde, ist die von Dir bereits genannte Fehlermeldung da.
Ich teste gleichmal.
Was die Reihenfolge von SpringApplication.run(..) und JFrame angeht, glaube ich nicht, dass sie wichtig ist, da ich eine Spring-Boot-Shell Komponente verwenden. Da rufe ich die Methode auf und es läuft.

Du kannst es auch erzwingen, in dem Du java.awt.headless=false setzt. (Als jvm Parameter mittels -D)

Das kannst du - wenn Du es über mvn spring-boot:run starten können willst, z.B. so setzen:
XML:
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <jvmArguments>-Djava.awt.headless=false</jvmArguments>
                </configuration>
            </plugin>

Oder halt als JVM Option in der Run Configuration eintragen.
Genaue an so etwas habe ich gedacht
 

KonradN

Super-Moderator
Mitarbeiter
Was die Reihenfolge von SpringApplication.run(..) und JFrame angeht, glaube ich nicht, dass sie wichtig ist, da ich eine Spring-Boot-Shell Komponente verwenden.
Genau das habe ich ausgetestet, denn diese Fehlermeldung hatte ich in der Vergangenheit nie. Daher war ich mir sicher, dass es gehen müsste und meine Versuche haben es klar gezeigt:

Java:
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
        SwingUtilities.invokeLater( () -> {
==> Exception kommt

Java:
    public static void main(String[] args) {
        SwingUtilities.invokeLater( () -> {
            JFrame frame = new JFrame("Test");
            frame.setSize(500, 300);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            JButton button = new JButton("Test");
            frame.add(button);
            frame.setVisible(true);

            button.addActionListener( e -> {
                JOptionPane.showMessageDialog(frame, "Button clicked!");
            });

        });

        SpringApplication.run(DemoApplication.class, args);
    }

==> Keine Exception und Anwendung läuft.
 

ExceptionOfExpectation

Aktives Mitglied
Nach der Korrektur im Pom.xml habe ich folgende Fehlermeldung:

Rich (BB-Code):
java.awt.HeadlessException
    at java.desktop/java.awt.GraphicsEnvironment.checkHeadless(GraphicsEnvironment.java:166)
    at java.desktop/java.awt.Window.<init>(Window.java:553)
    at java.desktop/java.awt.Frame.<init>(Frame.java:428)
    at java.desktop/java.awt.Frame.<init>(Frame.java:393)
    at java.desktop/javax.swing.JFrame.<init>(JFrame.java:180)
    at com.tutego.date4u.components.AppJFrame.<init>(AppJFrame.java:23)
    at com.tutego.date4u.config.EntityManagerCommands.createImageView(EntityManagerCommands.java:82)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:352)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:713)
    at com.tutego.date4u.config.EntityManagerCommands$$SpringCGLIB$$0.createImageView(<generated>)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.springframework.shell.command.invocation.InvocableShellMethod.doInvoke(InvocableShellMethod.java:306)
    at org.springframework.shell.command.invocation.InvocableShellMethod.invoke(InvocableShellMethod.java:232)
    at org.springframework.shell.command.CommandExecution$DefaultCommandExecution.evaluate(CommandExecution.java:227)
    at org.springframework.shell.Shell.evaluate(Shell.java:248)
    at org.springframework.shell.Shell.run(Shell.java:159)
    at org.springframework.shell.jline.InteractiveShellRunner.run(InteractiveShellRunner.java:73)
    at org.springframework.shell.DefaultShellApplicationRunner.run(DefaultShellApplicationRunner.java:65)
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:777)
    at org.springframework.boot.SpringApplication.lambda$callRunners$3(SpringApplication.java:767)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
    at java.base/java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:357)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:510)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
    at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:765)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:330)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1342)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1331)
    at com.tutego.date4u.Date4uAppApplication.main(Date4uAppApplication.java:24)
Diese Exception wird bei meiner Variante nicht geworfen.
Ich möchte, dass es nach jedem Methodenaufruf in Shell-Commando neues Desktop-Applikation erstellt wird. Das mit der zentrale Applikation in der main-Methode ist nicht bei der Aufgabe erwünscht.
 

ExceptionOfExpectation

Aktives Mitglied
Genau das habe ich ausgetestet, denn diese Fehlermeldung hatte ich in der Vergangenheit nie. Daher war ich mir sicher, dass es gehen müsste und meine Versuche haben es klar gezeigt:

Java:
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
        SwingUtilities.invokeLater( () -> {
==> Exception kommt

Java:
    public static void main(String[] args) {
        SwingUtilities.invokeLater( () -> {
            JFrame frame = new JFrame("Test");
            frame.setSize(500, 300);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            JButton button = new JButton("Test");
            frame.add(button);
            frame.setVisible(true);

            button.addActionListener( e -> {
                JOptionPane.showMessageDialog(frame, "Button clicked!");
            });

        });

        SpringApplication.run(DemoApplication.class, args);
    }

==> Keine Exception und Anwendung läuft.
Also bei der Variante läuft es genau so wie ich es wollte, nach jedem Methodenaufruf wurde neue Applikation gebildet und es wurde keine HeadlessException geworfen.
Java:
@SpringBootApplication
@EnableCaching
public class Date4uAppApplication {

    public static void main(String[] args) {
        SpringApplicationBuilder builder = new SpringApplicationBuilder(Date4uAppApplication.class);
        builder.headless(false);
        ConfigurableApplicationContext context = builder.run(args);
    }
}
Nun wollte ich es anders gemanagt haben, getrennt in einer anderen Datei.
 

KonradN

Super-Moderator
Mitarbeiter
Ich möchte, dass es nach jedem Methodenaufruf in Shell-Commando neues Desktop-Applikation erstellt wird. Das mit der zentrale Applikation in der main-Methode ist nicht bei der Aufgabe erwünscht.
Es sollte ausreichen, einfach nur den EDT Thread zu initialisieren. Das können wir testen, in dem wir die Variante nutzen, bei der de Exception geworfen wird und fügen dann zuerst einfach ein invokeLater Aufruf ein:

Java:
    public static void main(String[] args) {
        SwingUtilities.invokeLater( () -> { });

        SpringApplication.run(DemoApplication.class, args);

        SwingUtilities.invokeLater( () -> {

==> Keine Exception. Sprich: Es reicht, den EDT in der Main Methode zuerst zu initialisieren und dann sollte es möglich sein, aus der Spring Boot Anwendung heraus die JFrames zu erzeugen.

Wenn Du aber zu JavaFX wechseln willst, dann ist die Frage, wie man es da umsetzt. Evtl. lässt man die main Methode nur die JavaFX Anwendung starten und macht dann en Start der SpringBoot Anwendung in der start Methode von Application. Dann sollte alles soweit initialisiert worden sein.

Eine Problematik könnte dann nur sein, dass JavaFX gerne modularisiert ist. Das sollte beim aktuellen Spring Boot jetzt wohl auch gehen, aber da habe ich keine Erfahrungen und ich habe das halt nur gelesen.
Das kann es ggf. alles etwas verkomplizieren zumal auch die JavaFX bei der Initialisierung etwas zicken kann und so.
Aber das kannst Du ja ausprobieren und den jvm Parameter -Djava.awt.headless=false hast Du zur Not bezüglich dieses Problemes auch (neben der Lösung, das im Builder mit anzugeben).
 

ExceptionOfExpectation

Aktives Mitglied
Es sollte ausreichen, einfach nur den EDT Thread zu initialisieren. Das können wir testen, in dem wir die Variante nutzen, bei der de Exception geworfen wird und fügen dann zuerst einfach ein invokeLater Aufruf ein:

Java:
    public static void main(String[] args) {
        SwingUtilities.invokeLater( () -> { });

        SpringApplication.run(DemoApplication.class, args);

        SwingUtilities.invokeLater( () -> {

==> Keine Exception. Sprich: Es reicht, den EDT in der Main Methode zuerst zu initialisieren und dann sollte es möglich sein, aus der Spring Boot Anwendung heraus die JFrames zu erzeugen.

Wenn Du aber zu JavaFX wechseln willst, dann ist die Frage, wie man es da umsetzt. Evtl. lässt man die main Methode nur die JavaFX Anwendung starten und macht dann en Start der SpringBoot Anwendung in der start Methode von Application. Dann sollte alles soweit initialisiert worden sein.

Eine Problematik könnte dann nur sein, dass JavaFX gerne modularisiert ist. Das sollte beim aktuellen Spring Boot jetzt wohl auch gehen, aber da habe ich keine Erfahrungen und ich habe das halt nur gelesen.
Das kann es ggf. alles etwas verkomplizieren zumal auch die JavaFX bei der Initialisierung etwas zicken kann und so.
Aber das kannst Du ja ausprobieren und den jvm Parameter -Djava.awt.headless=false hast Du zur Not bezüglich dieses Problemes auch (neben der Lösung, das im Builder mit anzugeben).
So funktioniert das, ich kann so oft wie ich will neue Desktop-Applikationen erstellen. Mit dem JavaFX, experimentiere ich noch, mir gefällt es besser als von Swing, denn bei der JavaFX ist alles besser strukturiert.
Danke, es half weiterzukommen!
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
V Spring Sinnhafigkeit in Enduser Desktop Anwendung Frameworks - Spring, Play, Blade, Vaadin & Co 2
ExceptionOfExpectation Persistierung in Hibernate(SpringBoot) Frameworks - Spring, Play, Blade, Vaadin & Co 2
S java springboot HTML Produktstruktur Frameworks - Spring, Play, Blade, Vaadin & Co 1
G Java springboot Item mit ItemInstance verbinden Frameworks - Spring, Play, Blade, Vaadin & Co 2
ExceptionOfExpectation @Value() für application.properties [SpringBoot] Frameworks - Spring, Play, Blade, Vaadin & Co 9
Zrebna SpringBoot: Einfache RestAPI konsumieren gelingt nicht. Frameworks - Spring, Play, Blade, Vaadin & Co 6
Zrebna SpringBoot-Project: java.sql.SQLSyntaxErrorException: Access denied for user 'gap3'@'%' to database '3306/gap3' Frameworks - Spring, Play, Blade, Vaadin & Co 3
D SpringBoot Properties und Docker Frameworks - Spring, Play, Blade, Vaadin & Co 8
Dimax SpringBoot native Querry return ArrayList Frameworks - Spring, Play, Blade, Vaadin & Co 6
OnDemand SpringBoot Logrotation funktioniert nicht Frameworks - Spring, Play, Blade, Vaadin & Co 6
Robertop Springboot Server kann Jakarta Persistence Root nicht installieren? Frameworks - Spring, Play, Blade, Vaadin & Co 0
G SpringBoot MVC Frameworks - Spring, Play, Blade, Vaadin & Co 1
tom.j85 SpringBoot Rest-Application funktioniert nicht - Keine Fehlermeldungen Frameworks - Spring, Play, Blade, Vaadin & Co 13
V SpringBoot/Thymeleaf ein Attribut zum Controller schicken Frameworks - Spring, Play, Blade, Vaadin & Co 10
L OpenJFX, SpringBoot und Gradle Frameworks - Spring, Play, Blade, Vaadin & Co 12
L SpringBoot Web Application Frameworks - Spring, Play, Blade, Vaadin & Co 1
S SpringBoot MySQL not run Frameworks - Spring, Play, Blade, Vaadin & Co 5
B Springboot und LDAP - Authentifizieren gegen Gruppe Frameworks - Spring, Play, Blade, Vaadin & Co 3
R Authentifizieren mit SpringBoot Frameworks - Spring, Play, Blade, Vaadin & Co 4
M Günstigste oder kostenlose Variante SpringBoot Application laufen zu lassen Frameworks - Spring, Play, Blade, Vaadin & Co 7
Z Springboot - Hauptklasse nicht gefunden Frameworks - Spring, Play, Blade, Vaadin & Co 5
A SpringCloud | SpringBoot | Eureka Frameworks - Spring, Play, Blade, Vaadin & Co 0

Ähnliche Java Themen

Neue Themen


Oben