Tanguy HELLER
Tanguy HELLER

Reputation: 39

How to display error message in dialog from catched exception in a background task javaFX?

I am building javaFX user-interface with user interaction between the windows and I'm running into an issue I can't find solution anywhere...

So basically I want to open a dialog with inputs that can be filled by user, once done the app launch a background task with these informations, and an other dialog show up while the task is running (a loading screen). BUT ! Error can occurs during the task and exceptions can be catched, if it appens I want to display the exception message in another dialog for the user.

So, in a first place I have my dialog with input(s) :

// Init dialog
Dialog<String> inputDialog = new Dialog<>();
inputDialog.setTitle("Meshes generation parameters");
// Add validation buttons
inputDialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, 
ButtonType.CANCEL);
// Creating content
GridPane gridPane = new GridPane();
TextField width = new TextField("15000");
gridPane.add(new Label("Width (meters)"), 0, 0);
gridPane.add(width, 1, 0);
// Filling dialog
inputDialog.getDialogPane().setContent(gridPane);

// Returning result with OK button
inputDialog.setResultConverter(dialogButton -> {
        if (dialogButton == ButtonType.OK) {
            return width.getText();
        }
        return null;
    });

// Opens dialog until user close it or validate it.
Optional<String> result = inputDialog.showAndWait();

And then if the result is triggered I create a task :

result.ifPresent(width -> {
// Creates task that will run in background
Task task= new Task() {
    @Override
    protected Object call() throws Exception {
        try {
            // Do things with 'width'
        } catch (Exception e) {
            system.out.println("Exception catched in task !");
            // Tried to open dialog from here but it never shows
        }
        return null;
    }
}; // End of task

// Open 'loading screen' dialog until task ends
ProgressDialog dialog = new ProgressDialog(meshesGeneration);
dialog.initStyle(StageStyle.TRANSPARENT);
dialog.setTitle("Please wait.");
dialog.setHeaderText("This may take some time, please wait.");
dialog.initStyle(StageStyle.UTILITY);
// Runs the task
new Thread(task).start();
dialog.showAndWait();

});

Everything is working great, the ProgressDialog shows until the task is finished no matter if it fails or succeed. I can display in console that the exception has been catched, but the dialog created in the catch never shows.

I tried different things like :

task.setOnFailed(e -> {
    system.out.println(task.getException().getMessage()); // Nothing
});

I also tried to add state or exception inside the task itself ...

} catch (Exception e) {
    system.out.println("Exception caught in task !");
    failed();
    setException(e);
}

But I nothing seems to happend... I even get a SUCCEEDED state with the exception beeing catched and a nullPointerException for searching task.getException() (Calling thos two lines outside the task in the result.ifPresent{...)!

I'm pretty noob in multithreading... Did I miss something ? Any help will be very appreciated, thank you :)

Upvotes: 0

Views: 2710

Answers (2)

fabian
fabian

Reputation: 82461

The code works fine assuming you're opening the dialog properly:

} catch (Exception e) {
    System.out.println("Exception caught in task!");
    Platform.runLater(() -> {
        Alert dialog = new Alert(AlertType.ERROR, "Error", ButtonType.OK);
        dialog.show();
    });
}

The standard approach for exceptions that triggers the onFailed handler though is exiting the call method with an exception:

} catch (Exception e) {
    System.out.println("Exception caught in task!");
    throw e;
}

Instead of rethrowing the exception you could simply remove the try-catch, but this no longer allows you to print the message to the console inside the task.

task.setOnFailed(evt -> {
    System.out.println(task.getException().getMessage());
    Alert dialog = new Alert(AlertType.ERROR, "Error", ButtonType.OK);
    dialog.show();
});

Upvotes: 1

Gnas
Gnas

Reputation: 718

Try displaying it inside Platform.runLater

Upvotes: 1

Related Questions