16

I am trying to set up a background service that would perform bulk loading of transaction data from a csv file. This background service would be initiated from a menu item action mapped to a method in the controller/presenter class.

Ever so often, some data turns up in the csv file for which no master data can be found in the database, this would normally cause the upload to choke and fail.

On such occasions, I would like to be able to have the background service pause its processing and invoke a dialog from a presenter class to take in user input. The user input would be used to add a master row in the database, after which the background service should resume from where it had left off (not from the beginning of the csv file, but from the row which caused the error).

Is this possible to achieve in JavaFX, perhaps with the javafx.concurrent API? How would I go about doing this?

Lambda II
  • 173
  • 1
  • 7

1 Answers1

24

Solution

When your background process encounters a situation where it requires a user to be prompted for input, use FutureTask executed in Platform.runLater to showAndWait the dialog prompt on the JavaFX application thread. In the background process use futureTask.get to pause the background process until the user has input the necessary values which will allow the process to continue.


Sample Code Snippet

Here is the essence of code for this approach which can be placed inside the call method of your background process:

String nextText = readLineFromSource();
if ("MISSING".equals(nextText)) {
  updateMessage("Prompting for missing text");
  FutureTask<String> futureTask = new FutureTask(
    new MissingTextPrompt()
  );
  Platform.runLater(futureTask);
  nextText = futureTask.get();
}
...
class MissingTextPrompt implements Callable<String> {
  private TextField textField;

  @Override public String call() throws Exception {
    final Stage dialog = new Stage();
    dialog.setScene(createDialogScene());
    dialog.showAndWait();
    return textField.getText();
  }
  ...
}

Sample Application

I created a small, complete sample application to demonstrate this approach.

The output of the sample application is:

promptingtaskdemooutput

Sample Output Explanation

Lines read without missing values are just plain brown. Lines with a prompt value entered have a pale green background. Fourteen lines have been read, the background task has already paused once at the 6th line which was missing a value. The user was prompted for the missing value (to which the user entered xyzzy), then the process continued until line 14 which is also missing and the background task is again paused and another prompt dialog is being displayed.

jewelsea
  • 150,031
  • 14
  • 366
  • 406
  • 1
    Excellent, this looks like it would do the job. Thanks. – Lambda II Feb 22 '13 at 12:21
  • Thank you for taking the time to provide a solution; a modification of this does appear to solve my problem. However I see a most curious behavior in the sample code that you have provided. If I modify the input string and set the first token to 'MISSING', the program hangs; the dialog window to take in user input does not pop up. But, if I proceed to debug it (in NetBeans 7.2), it works just fine. Any idea what's happening here? – Lambda II Feb 25 '13 at 17:05
  • There was a bug in the sample code. The sample uses `container.getScene().getWindow()` within a task which was (correctly) throwing an (unreported) `NullPointerException` when the container hadn't yet been added to a scene. I changed the logic order in the sample so that the task is not started until the container it uses has been added to the scene (which avoids the issue). [Updated sample code linked](https://gist.github.com/jewelsea/4989970). – jewelsea Feb 25 '13 at 18:22
  • DataFX 8 contains invokeAndWait methods: www.datafx.io Here is an example how you can write your own method: http://www.guigarage.com/2013/01/invokeandwait-for-javafx/ – Hendrik Ebbers Oct 14 '14 at 10:31
  • Thankyou so much ! You saved my life – Prateek Mishra Jun 15 '16 at 12:27