JavaFX Alert Confirmation Dialog aus einem Service Thread

ralfb1105

Bekanntes Mitglied
Hallo zusammen,

ich habe schon wieder eine Frage/Problematik wo ich nicht so recht weiter komme und hoffe Ihr könnt mir wieder mal helfen.
Hier kurz die Beschreibung meiner Thematik die ich lösen möchte:
Ich habe einen Service Thread in dem ich verschiedene Tasks durchführe, wie z.B:
  • Task 1: Check if ojdbc driver is available.
  • Task 2: Try database connection. Printout Java and JDBC Version
  • Task 3: Check the database version
Nun hat der User noch die Möglichkeit, bei Bedarf einen "normalen" DB User anzugeben, und wenn der gesetzt ist, soll überprüft werden ob es den User in der DB schon gibt. Falls es den User noch nicht gibt, soll ein Confirmation Dialog angezeigt werden der den User zur Bestätigung zum erstellen des User auffordert.

Den Confirmation Dialog habe folgendermassen codiert:
Java:
private void showConfirmationDialogUserCreation() {
        Alert confirmUserCreation = new Alert(AlertType.CONFIRMATION);
        confirmUserCreation.setTitle("Create User");
        confirmUserCreation
                .setHeaderText("User doesn't exist.\nDo you want to create the user with the given credentials?");
        // confirmUserCreation.setContentText("Create User hr");

        // Create new Buttons
        ButtonType createUser = new ButtonType("Create User");
        ButtonType cancel = new ButtonType("Cancel");

        // Remove default ButtonTypes
        confirmUserCreation.getButtonTypes().clear();
       
        // Set new defined Buttons
        confirmUserCreation.getButtonTypes().addAll(createUser, cancel);

        Optional<ButtonType> option = confirmUserCreation.showAndWait();

        if (option.get() == null) {
            LOGGER.severe("Entered User Confirmation Dialog: No selection!");
        } else if (option.get() == createUser) {
            System.out.println("User hr created");
        } else if (option.get() == cancel) {
            System.out.println("User declined to create User hr");
        } else {
            LOGGER.severe("Entered User Confirmation Dialog case where we shouldn't be ...");
        }

    }
Im Service Thread sieht der Abschnitt dann folgendermaßen aus:
Java:
// Worker Thread called when DB Connect Button tapped ...
    @SuppressWarnings("rawtypes")
    Service serviceWorkerConnectDB = new Service() {
        String dbBanner;

        @Override
        protected Task createTask() {
            return new Task() {
                @Override
                protected Void call() throws Exception {
                    // Start enetering execution code here ...
...
...
// Task 4: If Username entered try connection as normal user ...
                    if (!dbUserName.getText().isEmpty()) {
                        updateMessage("Task4: Check if User " + dbUserName.getText() + " exists.");
                        LOGGER.info("Task4: Check if User " + dbUserName.getText() + " exists.");
                        String queryCheckIfUserExist = "select USERNAME from dba_users where USERNAME='" + dbUserName.getText().toUpperCase() + "'";
                        Statement stmtCheckIfUserExist = connSys.createStatement();
                        ResultSet rsetCheckUser = stmtCheckIfUserExist.executeQuery(queryCheckIfUserExist);
                        if (rsetCheckUser.next()) {
                            String user = rsetCheckUser.getString("USERNAME");
                            if (user.equalsIgnoreCase(dbUserName.getText())) {
                                updateMessage("Task4: Check if User " + dbUserName.getText() + " exists: Success!");
                                LOGGER.info("Task4: Check if User " + dbUserName.getText() + " exists: Success!");   
                            }
                        } else {
                            updateMessage("Task4: Check if User " + dbUserName.getText() + " exists: User does not exist.");
                            LOGGER.info("Task4: Check if User " + dbUserName.getText() + " exists: User does not exist!");
                                showConfirmationDialogUserCreation();   
                        }
                    }
                   

                    // End handling ...
                    updateProgress(1.0, 1.0);
                    connectDB.setDisable(false);
                    dbPatchInfo.setDisable(false);
                    connSys.close();
                    // End entering execution code here ...
                    return null;
                }

Wenn ich das programm starte und es den eingegeben User nicht gibt, dann endet das Programm nicht aber der Confirmation Dialog wird nicht angezeigt.

Wenn ich das mit einem
Java:
Platform.runLater(() -> {
                                showConfirmationDialogUserCreation();
                            });
mache, dann wird der Dialog angezeigt, ABER das programm, sprich der Service Task läuft natürlich weiter, was ja auch nicht so gewollt ist.

Frage:

Wie kann ich in dem Service Task den Confirmation Dialog anzeigen so dass der Servcie Task an der Stelle auf die User Bestätigung wartet und ich dann auch das Ergebniss (Create User oder Cancel) im weiteren Verlauf des Servcie Task weiter verabeiten kann --> User in der DB erstellen order im Programm ohne Erstellung eines User weiter machen?

Gruß

Ralf
 

ralfb1105

Bekanntes Mitglied
Hallo zusammen,

da es bis jetzt keine Antworten auf meine Frage gibt vermute ich mal das ich das Problem bzw. die Fragestellung nicht konkret genug gestellt habe. Falls jemand eine Frage zu meiner Darstellung hat oder auch nur eine Idee - einfach melden - bin für jeden Hinweis dankbar.

Gruß
Ralf
 

mihe7

Top Contributor
Mal eine Idee:
Java:
import java.util.Optional;
import java.util.concurrent.atomic.*;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.*;
import javafx.concurrent.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.control.Alert.AlertType;
import javafx.stage.*;

public class Background extends Application {
    private StringProperty status = new SimpleStringProperty("NOT RUNNING");
    private Task<Void> task = new Task<Void>() {
        @Override
        protected Void call() throws Exception {
            Platform.runLater(() -> status.set("Step 1"));
            Thread.sleep(1000);
            Platform.runLater(() -> status.set("Step 2"));
            Thread.sleep(1000);
            AtomicInteger value = new AtomicInteger();
            synchronized(value) {
                Platform.runLater(() -> getInput(value));
                value.wait();
            }
            Platform.runLater(() -> status.set("Step 3"));
            Thread.sleep(1000);
            return null;
        }
    };

    private void getInput(AtomicInteger result) {
        Alert confirmUserCreation = new Alert(AlertType.CONFIRMATION);
        confirmUserCreation.setTitle("Create User");
        confirmUserCreation
                .setHeaderText("User doesn't exist.\nDo you want to create the user with the given credentials?");
        // confirmUserCreation.setContentText("Create User hr");

        // Create new Buttons
        ButtonType createUser = new ButtonType("Create User");
        ButtonType cancel = new ButtonType("Cancel");

        // Remove default ButtonTypes
        confirmUserCreation.getButtonTypes().clear();
       
        // Set new defined Buttons
        confirmUserCreation.getButtonTypes().addAll(createUser, cancel);

        Optional<ButtonType> option = confirmUserCreation.showAndWait();
        int r = 0;

        if (option.get() == null) {
        } else if (option.get() == createUser) {
            r = 1;
            System.out.println("User hr created");
        } else if (option.get() == cancel) {
            r = 2;
            System.out.println("User declined to create User hr");
        } else {
            r = 3;
        }
        synchronized(result) {
            result.set(r);
            result.notify();
        }
    }


    public void start(Stage s) {
        Label lbl = new Label();
        lbl.textProperty().bind(status);
        Scene scene = new Scene(lbl);
        s.setScene(scene);
        s.show();

        new Thread(task).start();
    }
}
 

ralfb1105

Bekanntes Mitglied
Hallo mihe7,

DANKE! Deine Idee funktioniert bei mir auf den ersten Blick/Test super :D.
Ich habe dazu noch folgende Frage, damit ich auch wieder etwas von dem verstehe was Ihr mir alles beibringt ...
1. Warum muss ich hier als Integer den AtomicInteger nehmen ? Thread sicher? Methoden ?
2. Die .wait(), .set() und .notify() Methoden .. die wait und notify beziehen sich auf den Thread und sie set() auf den AtomicInteger?!

Gruß
Ralf
 

mihe7

Top Contributor
damit ich auch wieder etwas von dem verstehe
Das hatte ich gestern ganz überlesen. Ein paar Zusatzinformationen zum Monitor in Java findest Du unter https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html

Zur Erklärung des Codes: mit synchronized(o) verschafft man sich exklusiven Zugriff auf den Monitor des Objekts o (sollte der belegt sein, muss man ggf. warten, bis er wieder frei ist). Bei o.wait(); passieren zwei Dinge: man legt den aktuellen Thread schlafen, nachdem er in die Warteschlange des Monitors von o eingereiht wurde. Bei o.notify(); wird ein Thread aus der Warteschlange des Monitors von o aufgeweckt.

Etwas konkreter auf den Code bezogen: der Task nimmt ein AtomicInteger-Objekt (dazu gleich mehr), verschafft sich exklusiven Zugriff auf dessen Monitor, übergibt das Objekt an eine Methode, die "später" im UI-Thread ausgeführt wird und wartet nun auf Benachrichtigung vom Monitor; dabei wird der Monitor freigegeben.

Die im UI-Thread aufgerufene Methode verschafft sich ebenfalls exklusiven Zugriff auf den Monitor des übergebenen Objekts (das AtomicInteger-Objekt von eben). Damit ist nebenbei sichergestellt, dass entweder der Task oder der UI-Thread auf das AtomicInteger-Objekt zugreifen, niemals aber beide gleichzeitig. Via notify() wird dem Monitor mitgeteilt, dass es einen wartenden Thread (Deinen Task) aufwecken kann.

Für diesen Zweck kannst Du jedes x-beliebige Objekt verwenden - es muss in beiden Threads nur das selbe(!) Objekt sein.

Der Code oben ist noch nicht ganz vollständig, da tatsächlich auf eine Bedingung gewartet wird, die nicht abgeprüft wird. Die Bedingung könnte man salopp so formulieren: "Task wurde von der aufgerufenen Methode aufgeweckt". Hintergrund ist, dass es sog. spurious wakeups gibt, d. h. Threads werden aufgeweckt, obwohl gar kein notify() aufgerufen wurde. Deswegen müsste das wait oben noch in eine Schleife gepackt werden, die eine entsprechende Bedingung überprüft.

Kommen wir zum AtomicInteger: das ist tatsächlich nur dazu da, irgendeinen Rückgabewert speichern zu können. Alternativ könntest Du z. B. auch den Dialog in eine Klasse auslagern und den Rückgabewert in einer Instanzvariablen speichern. Dann erzeugst Du im Background-Thread ein Objekt von der Dialog-Klasse und arbeitest mit diesem. Du kannst das notify() auch über einen Listener bzw. JavaFX Callback erledigen usw. Möglichkeiten gibt es genügend - auch andere (aber ähnliche) Ansätze.

Ein ganz anderer Ansatz wäre z. B. die Tasks aufzudröseln und dann per Listener im UI-Thread auf Beendigung zu reagieren:

Task 1 -> fertig -> starte Task 2
Task 2 -> fertig -> starte Task 3
Task 3 -> fertig -> Task 4 ist dann eigentlich kein Background-Task sondern einfach der Dialog-Aufruf, im Anschluss ginge es dann weiter mit dem Starten des nächsten Tasks.
 

ralfb1105

Bekanntes Mitglied
Hallo mihe7,

vielen Dank für Deine ausführlichen und sehr verständlichen Erklärungen!!!
Ich habe noch eine Frage zu
Der Code oben ist noch nicht ganz vollständig, da tatsächlich auf eine Bedingung gewartet wird, die nicht abgeprüft wird. Die Bedingung könnte man salopp so formulieren: "Task wurde von der aufgerufenen Methode aufgeweckt". Hintergrund ist, dass es sog. spurious wakeups gibt, d. h. Threads werden aufgeweckt, obwohl gar kein notify() aufgerufen wurde. Deswegen müsste das wait oben noch in eine Schleife gepackt werden, die eine entsprechende Bedingung überprüft.
Ich vermute es geht um folgenden Code:
Code:
AtomicInteger value = new AtomicInteger();
                            synchronized(value) {
                                Platform.runLater(() -> getInputConfirmationDialogCreateUser(value));
                                value.wait();
                            }
und hier im speziellen um "value.wait();" - richtig?

Mir ist nicht ganz klar wie ich nun überprüfe ob es der "echte" notify() war oder irgendein "spurious wakepup". Ich habe keine Methode gefunden die ich jetzt so in einer Abfrage verwenden könnte um zu entscheiden ob der notify() des AtomicInteger Objekts gekommen ist.

Gruß
Ralf
 

mihe7

Top Contributor
und hier im speziellen um "value.wait();" - richtig?
Ja.
Ich habe keine Methode gefunden die ich jetzt so in einer Abfrage verwenden könnte um zu entscheiden ob der notify() des AtomicInteger Objekts gekommen ist.
Das funktioniert über den Rückgabewert. Wenn die Methode z. B. Werte ab 0 zurückgibt, dann setzt Du den Wert vorher halt auf einen negativen Wert:
Java:
AtomicInteger value = new AtomicInteger();
value.set(-1);
while (value.get() == -1) {
    synchronized(value) {
        Platform.runLater(() -> getInputConfirmationDialogCreateUser(value));
        value.wait();
    }
}
 

ralfb1105

Bekanntes Mitglied
Hallo mihe7,

nochmals Danke! Ich muss zugeben das ich darauf nicht gekommen wäre, auch wenn es so einleuchtend ist wenn ich es jetzt lese. Ich werde das Morgen gleich mal testen.

Gruß
Ralf
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
I Fehler bei Alert AWT, Swing, JavaFX & SWT 6
melaniemueller Confirmation Dialog erstellen AWT, Swing, JavaFX & SWT 18
B Confirmation Dialog AWT, Swing, JavaFX & SWT 2
MiHimbert Rückmeldung an den aufrufenden JAVAFX-Dialog AWT, Swing, JavaFX & SWT 1
H AWT Dialog Größe ändern - Schwarzer Inhalt beim groß ziehen AWT, Swing, JavaFX & SWT 1
L Swing Files abspeichern mit Save as Dialog Fenster AWT, Swing, JavaFX & SWT 5
N JavaFX Vor beenden der Anwendung durch klicken von X Dialog zeigen AWT, Swing, JavaFX & SWT 1
C Swing Aufruf der Funktion (die ein Dialog anzeigt) über Symbol anzeigen lassen AWT, Swing, JavaFX & SWT 4
H Eigener Dialog mit Rückgabe -> Warten auf Button AWT, Swing, JavaFX & SWT 3
kodela Swing Problem mit Warten-Dialog AWT, Swing, JavaFX & SWT 16
G JavaFX JavaFX-Dialog aus einer Nicht-JavaFX-Anwendung heraus AWT, Swing, JavaFX & SWT 1
C FileChooser Save-Dialog zeigt Files nicht an AWT, Swing, JavaFX & SWT 3
S AWT Java print dialog Problem AWT, Swing, JavaFX & SWT 0
E Swing Dialog modal aufrufen AWT, Swing, JavaFX & SWT 2
T JavaFX Dialog schließt ohne dass es schließen soll AWT, Swing, JavaFX & SWT 1
RalleYTN Modaler Dialog und JTree Node mit sehr... seeeeehr vielen Elementen AWT, Swing, JavaFX & SWT 6
T JOptionPane Dialog plus Rechnung ausgeben AWT, Swing, JavaFX & SWT 1
krgewb AWT JFrame soll sich wie Dialog verhalten AWT, Swing, JavaFX & SWT 9
J JavaFX Dialog - Style AWT, Swing, JavaFX & SWT 6
D Swing Dynamisches Dialog UI AWT, Swing, JavaFX & SWT 8
H JFileChooser Dateinamen vorgeben (Save Dialog) AWT, Swing, JavaFX & SWT 9
D Neues Dialog Mittig auf dem Bildschirm AWT, Swing, JavaFX & SWT 4
F 2D-Grafik Grafikproblem nach Aufruf von JColorChooser-Dialog AWT, Swing, JavaFX & SWT 6
M Java FX Innerhalb einem FXML-Dialog weiteren FXML-Dialog einblenden AWT, Swing, JavaFX & SWT 3
T SWT SWTBot Test: Dialog soll sich öffnen,wenn button gedrückt AWT, Swing, JavaFX & SWT 3
G Datei öffnen Dialog modifizieren AWT, Swing, JavaFX & SWT 13
W SWT Dialog richtig schließen? AWT, Swing, JavaFX & SWT 0
M Benutzer-Dialog ohne System.in/out AWT, Swing, JavaFX & SWT 2
P JOptionPane input und show Message Dialog AWT, Swing, JavaFX & SWT 5
F Dialog mit Titel, Text und Ok Button AWT, Swing, JavaFX & SWT 2
TheWhiteShadow SWT Dialog Titel setzen AWT, Swing, JavaFX & SWT 6
VfL_Freak Darstellungsproblem mit Dialog AWT, Swing, JavaFX & SWT 8
P Swing Dialog zeigt keinen Inhalt in Verbindung mit JFrame AWT, Swing, JavaFX & SWT 18
G Nebenläufiger Prozess mit Dialog AWT, Swing, JavaFX & SWT 2
C Swing Fortschrittsanzeige im Dialog ohne Fortschrittsbalken und Abbruchoption AWT, Swing, JavaFX & SWT 7
M Swing Elemente im Dialog neu "laden". AWT, Swing, JavaFX & SWT 6
VfL_Freak Swing KeyListener, um einen Dialog per ESC zu schließen AWT, Swing, JavaFX & SWT 6
R DnD in modalem Dialog AWT, Swing, JavaFX & SWT 4
I Dialog zum Speichern? AWT, Swing, JavaFX & SWT 16
M Dialog soll etwas an "Oberklasse" übergeben AWT, Swing, JavaFX & SWT 3
qwerqer Swing JDialog Darstellungsprobleme - Dialog lässt sich nicht schließen AWT, Swing, JavaFX & SWT 3
M Datei Speichern unter Dialog - SWT AWT, Swing, JavaFX & SWT 3
hdi Swing Bzgl JFrame & modaler Dialog AWT, Swing, JavaFX & SWT 6
N Modaler Dialog wird nicht angezeigt AWT, Swing, JavaFX & SWT 8
J SWT Dialog in Dialog automatisch öffnen AWT, Swing, JavaFX & SWT 19
H Confirm Dialog erweitern AWT, Swing, JavaFX & SWT 5
K Modaler Dialog aber trotzdem Aktualisierung des MainFrames AWT, Swing, JavaFX & SWT 6
B Gestaltung eines Optionen-Dialog AWT, Swing, JavaFX & SWT 16
P Swing Option zeitbeschränkt in modalem Dialog anbieten AWT, Swing, JavaFX & SWT 2
X Einem JFrame einen Dialog als Parent setzen. Möglich? AWT, Swing, JavaFX & SWT 4
L AWT Window, Dialog und verschiedene Betriebssysteme AWT, Swing, JavaFX & SWT 2
T SWT Window Builder Pro File Dialog anzeigen AWT, Swing, JavaFX & SWT 10
A Swing Delay (1-4 Sek.) bei JTable und Dialog beim ersten Ausführen AWT, Swing, JavaFX & SWT 3
P Swing modaler dialog AWT, Swing, JavaFX & SWT 3
P SWT Dialog AWT, Swing, JavaFX & SWT 3
O Login Dialog zweimal öffnen AWT, Swing, JavaFX & SWT 2
B Datei öffnen Dialog AWT, Swing, JavaFX & SWT 9
N Swing eigenen Dialog erstellen AWT, Swing, JavaFX & SWT 8
C Swing Fehlermeldung in einem Dialog anzeigen AWT, Swing, JavaFX & SWT 2
L Dialog mit Dauerschleifen AWT, Swing, JavaFX & SWT 4
K SWT TableViewer refresh() im Dialog AWT, Swing, JavaFX & SWT 2
Semox Swing FileSaveAs Dialog Problem AWT, Swing, JavaFX & SWT 14
H Sub-Dialog von modalem JDialog aus aufrufen - geht das? AWT, Swing, JavaFX & SWT 6
B Dialog aus DB Struktur erstellen AWT, Swing, JavaFX & SWT 4
D URL Dialog AWT, Swing, JavaFX & SWT 2
B Swing Keylistener fuer Dialog-Buttons AWT, Swing, JavaFX & SWT 2
J nicht weckklickbarer dialog AWT, Swing, JavaFX & SWT 15
S Frame - Panel - Dialog rückgabe wert AWT, Swing, JavaFX & SWT 5
D Swing Dialog schließen verhindern bei Fehleingabe AWT, Swing, JavaFX & SWT 2
F JColorChooser NICHT im Dialog AWT, Swing, JavaFX & SWT 12
C Swing Mit jTree ein Ordneröffnen Dialog machen? Und Ordner Inhalt auslesen? AWT, Swing, JavaFX & SWT 4
N SWT Dialog mit swt-widgets AWT, Swing, JavaFX & SWT 5
L AWT Daten vom Dialog an Frame senden AWT, Swing, JavaFX & SWT 3
Lurch Swing Dialog erbt von Dialog? AWT, Swing, JavaFX & SWT 28
eQuest Durchsuchen Dialog AWT, Swing, JavaFX & SWT 6
D ausgewählte Textstellen scheinen durch Dialog durch AWT, Swing, JavaFX & SWT 7
S Modalen Dialog nachbauen..? AWT, Swing, JavaFX & SWT 4
E Swing Rückgabe eines Wertes aus einem Dialog zu einem Dialog AWT, Swing, JavaFX & SWT 4
W Swing Problem beim Passwort Dialog AWT, Swing, JavaFX & SWT 4
T Dialog ohne Frame, direktes paint in graphics AWT, Swing, JavaFX & SWT 5
C requestFocus bei modalem Dialog AWT, Swing, JavaFX & SWT 3
5 Mod.Dialog reagiert n.auf ActionListener seiner Komponenten AWT, Swing, JavaFX & SWT 4
A Bitte warten Dialog AWT, Swing, JavaFX & SWT 4
G SWT Dialog AWT, Swing, JavaFX & SWT 7
GilbertGrape EXIT_ON_CLOSE in Dialog AWT, Swing, JavaFX & SWT 3
T JFileChooser: beim Save Dialog einen Dateinamen vorgeben? AWT, Swing, JavaFX & SWT 6
K Druck-Dialog AWT, Swing, JavaFX & SWT 4
D JTable nach Öffnen-Dialog umbaun AWT, Swing, JavaFX & SWT 5
K Dialog schliesst sich nicht. Warum? AWT, Swing, JavaFX & SWT 11
K Automatisch einen Dialog schliessen AWT, Swing, JavaFX & SWT 15
J dialog AWT, Swing, JavaFX & SWT 5
H nicht modaler Dialog verdeckt modalen Dialog AWT, Swing, JavaFX & SWT 5
S Probl. bei Java Programm - Dialog zum Bearbeiten von Bildern AWT, Swing, JavaFX & SWT 4
W Wie macht man so nen Settings Dialog AWT, Swing, JavaFX & SWT 2
K Datei öffnen Dialog AWT, Swing, JavaFX & SWT 5
K Dialog aus einem Dialog öffnen AWT, Swing, JavaFX & SWT 4
S preference dialog öffnen AWT, Swing, JavaFX & SWT 8
spacegaier Fehler beim Aufrufen von Dialog aus ActionListener AWT, Swing, JavaFX & SWT 12
T DIALOG für BEENDEN AWT, Swing, JavaFX & SWT 11
N Dialog text bis zum nächsten öffnen sichern AWT, Swing, JavaFX & SWT 4

Ähnliche Java Themen

Neue Themen


Oben