/ DataFX / DataFX 8 Preview 2: The ProcessChain

DataFX 8 Preview 2: The ProcessChain

Hendrik on 2014/01/23 - 21:21 in DataFX, JavaFX

Some time ago I gave a first preview of the new APIs and functions in DataFX 8. We are currently plan to release DataFX 8 once JavaFX 8 is released. I plan to blog about the new features in DataFX in the next weeks. By doing so we hope to receive some useful feedback. In the last preview I described the controller and flow API of DataFX. Today I will show you only only small class :)

Next to new APIs we added some helpful classes to the DataFX core packages. The class that I want to show you today is one of these new classes: The ProcessChain.

The ProcessChain can be used to create a task chain. A task can be run on the “JavaFX Application Thread” or on a background thread. Some of you may know the SwingWorker class that was a important tool when working with background tasks in Swing. With the ProcessChain you can do similar stuff but thanks to Java 8, Lambdas and functional interfaces this class is more powerful that SwingWorker ever was.

Let’s think about a dialog that loads some data from a server. This can be done by clicking a button. Whenever the button is pressed the following workflow should be executed:

  • Disable Button
  • Communicate with Server
  • Enable Button

The button must enabled and disabled on the “JavaFX Application Thread” but you should not communicate with the server on this thread cause it will freeze the application. Because of that the communication must be executed on a extra thread:

  • Disable Button (Application Thread)
  • Communicate with Server (Background-Thread)
  • Enable Button (Application Thread)

The ProcessChain is a fluent API that can be used to create this workflows in JavaFX. Because its a chain you can add as many task as you want. The ProcessChain can use Lambdas and pass task results to the next Task. The following default interfaces can be used here:

  • java.util.function.Function
  • java.util.function.Supplier
  • java.util.function.Consumer
  • java.lang.Runnable

Here is a simple example:

Label label = new Label("No data");
Button button = new Button("Press meβ€œ);

button.setOnAction(new EventHandler() {

    public void handle(ActionEvent event) {

        new ProcessChain().inPlatformThread(() -> button.setDisable(true))
            .inExecutor(() -> communicateWithServer())
            .inExecutor(() -> {return "Time in Millis: " + System.currentTimeMillis();})
            .inPlatformThread((Consumer) (t) -> label.setText(t.toString()))
            .inPlatformThread(() -> button.setDisable(false))
            .run();
    }
});

As you can see in the example it is very easy to create a chain with the API. By using the inExecutor(…) or inPlatformThread(…) method a developer can choose if a task should run on the “JavaFX Application Thread” or in background.

In addition tasks can publish its result and use the result of the previous one. Here the new Java 8 interfaces Function, Supplier and Consumer can be used to define tasks with an input or output value.

The DataReader API is still part of DataFX of course. If you use DataReaders you shouldn’t need the shown API or can add all tasks to the Platform thread. But sometimes there are issues where you need to create your own custom background tasks. In these cases the ProcessChain is your friend πŸ˜‰

5 POST COMMENT

Send Us A Message Here

Your email address will not be published. Required fields are marked *

5 Comments
  • 2014/01/24

    Great. Thanks.

    Abdlquadri
    Reply
  • 2015/12/02

    Added 8.0b5 datafx-core to my project but have trouble.
    “inPlatformThread()” is not known / ” or “The method inPlatformThread(() -> {}) is undefined for the type ProcessChain”. I’m a beginner in JavaFX. Do you maybe can point me to some helpful information?
    I need to open JavaFX dialogs (introduced in Java8u40) on the application thread. As they are in an API I need to somehow prevent the JavaFX application thread to run and execute that code.

    marc
    Reply
    • 2015/12/02

      can you send me a code snippet? I currently don’t understand what you are trying.

      Reply
      • 2015/12/03

        I tried now with nearly the same code like you.

        Eclipse 4.5.1 with JDK 1.8.0.65 and DataFX “core-8.0.7.jar” shows Quick Fix for “new Eventhandler()”:
        “The type new EventHandler(){} must implement the inherited abstract method EventHandler.handle(Event)”

        Quick Fix for “.inPlatformThread()”:
        “The method inPlatformThread(() -> {}) is undefined for the type ProcessChain”

        In the called save() method there are dialogs opened by:
        Alert alert = new Alert(AlertType.ERROR);
        ..
        alert.showAndWait();

        Code, tried in a controller class that uses information from a FXML file:

        buttonsave.setOnAction(new EventHandler() {

        public void handle(ActionEvent event) {

        new ProcessChain().inPlatformThread(() -> buttonsave.setDisable(true))
        .inExecutor(() -> save())
        .inPlatformThread(() -> buttonsave.setDisable(false))
        .run();
        }
        });

        private void save() {
        //TBD
        }

        marc
        Reply
        • 2015/12/04

          I tried to open the javafx.scene.control.Alert in an javafx.concurrent.Task and got strange behavior, for example:

          Thread [JavaFX Application Thread] (Suspended (exception NullPointerException))
          InvokeLaterDispatcher$Future.run() line: 100 [local variables unavailable]
          WinApplication._runLoop(Runnable) line: not available [native method]
          WinApplication.lambda$null$149(int, Runnable) line: 191
          194494468.run() line: not available
          Thread.run() line: 745

          In this source code:

          @Override public void run() {
          try {
          this.runnable.run();
          } finally {
          synchronized (LOCK) {
          this.done = true;
          LOCK.notifyAll();
          }
          }
          }
          }

          So I tried to use ProcessChain with the problems shown above.

          Meanwhile I transferred the javafx.scene.control.Alert out of javafx.concurrent.Task. This solved my problem.

          Maybe I will try ProcessChain later again, which seems to really simplify things. Good work!

          marc
          Reply