NetBeans Platform Workflow Tutorial

This tutorial needs a review. You can edit it in GitHub following these contribution guidelines.

In this tutorial, you are shown how to create a pluggable infrastructure as the basis for a workflow application. In workflow applications, the user is guided through a sequence of steps provided by multiple GUI components, ending with a final product of some kind.

Here are two examples of workflow applications.

  • EasyDoe Toolsuite. A workflow created by IAV in Berlin, Germany, for control units of calibration engines, using a method called Design of Experiments. The workflow guides the user through the whole process, starting at defining the task, making a test plan, importing data, making a mathematical model from the data, using the model in optimizations and calibrate maps that are directly exported to the engine control units.

workflow 72 easyDoe thumb
  • Limits. A reservoir engineering tool created by Object Reservoir, in Austin, Texas, for shale gas and unconventional reservoirs. Limits uses readily available and routinely collected pressure and rate data to determine feasible ranges of physical reservoir and completion parameters in order to estimate the uncertainty in the future performance of the well.

workflow 72 objectreservoir thumb

In this tutorial, we imagine we’re creating a prediction system consisting of three steps, "specify", "diagnose", and "forecast". Each step in the sequence is supported by a "canvas", which consists of multiple "windows". The user switches from canvas to canvas via a control panel. Changes made by the user to the size and position of windows in a canvas are automatically stored on disk and are automatically available upon restarts of the application.

For troubleshooting purposes, you are welcome to download the completed tutorial source code.

Creating the Application

In this section, you create a skeleton prediction system, consisting of the NetBeans Platform.

  1. Choose File > New Project (Ctrl+Shift+N). Under Categories, select NetBeans Modules. Under Projects, select NetBeans Platform Application: javafx 72 new app 1 Click Next.

  1. In the Name and Location panel:

    • In the Project Name field, type PredictionSystem .

    • In the Project Location field, change the value to any directory on your computer where the application will be stored.

workflow 72 new project

Click Finish. The IDE creates the PredictionSystem project:

workflow 72 new app
  1. Right-click the application and choose Run. The application starts up, showing a default splash screen. Once the application has started, open some windows, browse through the menu bar and toolbar, and generally investigate the features that your application already has. workflow 72 new app 2

You now have a basic application containing a lot of functionality. In the next section, we create the canvases.

Creating the Canvases

In this section, you create support for the steps in the workflow, each of which consist of a canvas containing one or more windows.

Creating the Modular Structure

In this section, you create a new module for each step in the sequence.

  1. Right-click the application’s Modules node and choose Add New: workflow 72 new canvas 1 Click Next.

  1. Set Specify as the project name and leave the other values unchanged: workflow 72 new canvas 2 Click Next.

  1. Set org.prediction.specify as the module’s code name base and set Specify as the display name: workflow 72 new canvas 3 Click Finish. You now have your first custom module, named "Specify", for the code relating to the specify step: workflow 72 new canvas 4

  1. Repeat the three steps above twice, to create modules for the steps "diagnose" and "forecast": workflow 72 new canvas 5

You now have a modular structure on top of the NetBeans Platform. Each module will provide the code for one step in the workflow.

Creating the Windows

In this section, you create the windows that define the canvases.

  1. Right-click the org.prediction.specify package and choose New | Other | Module Development and then choose Window: workflow 72 new window 1 Click Next.

  1. Choose a window position, that is, the place in the application frame where the window will be displayed, and set Open on Application Start so that the window will open as soon as the application has started up: workflow 72 new window 2 Click Next.

  1. Set SpecifyOne (or another suitable name) as the class name prefix: workflow 72 new window 3 Click Finish. You now have your first window, named "SpecifyOneTopComponent", for the code relating to one of the windows in the specify step: workflow 72 new window 4

1. In the source code of the window, assign the window to its role, as follows, by adding roles={"specify"} in the @TopComponent.Registration annotation:

@TopComponent.Registration(*roles={"specify"},* mode = "editor", openAtStartup = true)
  1. Repeat the four steps above several times, to create several windows in each module, each window registered to the role for which you created the module. Each canvas is defined by multiple windows, some canvases will have more windows, while others have less. Dependending on the needs of each canvas, create the required windows accordingly, with appropriate names: workflow 72 new window 5

You now have three modules, each containing a canvas defined by one or more windows. In the next section, we create a controler mechanism so that the user can switch from canvas to canvas.

Creating the Controler Mechanism

In this section, you create a controler mechanism for switching between roles.

  1. As before, create a module in the application. Name it Control : workflow 72 new control 1

Click Next.

  1. Set org.prediction.control as the code name base: workflow 72 new control 2

Click Finish. You now have a Control module, together with the three canvas modules you already had:

workflow 72 new control 3
  1. In the Control module, right-click the Libraries node, and choose Add Module Dependency. Set a new module dependency on the Module System API and the Window System API.

  1. Create a new Java class named Installer in the package org.prediction.control . Define it as follows and click the links for further information:

package org.prediction.control;

import org.openide.modules.OnStart;
import org.openide.windows.WindowManager;
import org.openide.windows.WindowSystemEvent;
import org.openide.windows.WindowSystemListener;

@OnStart
public class Installer implements Runnable, WindowSystemListener  {

    @Override
    public void run() {
        WindowManager.getDefault().addWindowSystemListener(this);
    }

    @Override
    public void beforeLoad(WindowSystemEvent wse) {
        WindowManager.getDefault().setRole("specify");
        WindowManager.getDefault().removeWindowSystemListener(this);
    }

    @Override
    public void afterLoad(WindowSystemEvent wse) {
    }

    @Override
    public void beforeSave(WindowSystemEvent wse) {
    }

    @Override
    public void afterSave(WindowSystemEvent wse) {
    }

}
  1. In each window, delete the @ActionID , @ActionReference , and @TopComponent.OpenActionRegistration annotations because, instead of menu items for opening individual windows, you´re going to create a controler to open canvases, using one or more of the mechanisms described below.

Creating a Menu Based Controler Mechanism

In this section, you create new menu items to control switching between canvases.

In each canvas module, create an ActionListener such as the below for switching between roles. The example below is for the specify role, create the same class in the other two modules, changing "specify" to "diagnose" and "forecast" for the other modules.

package org.prediction.specify;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionRegistration;
import org.openide.util.NbBundle.Messages;
import org.openide.windows.WindowManager;

@ActionID(
        category = "Window",
        id = "org.prediction.specify.SwitchToSpecifyRole")
@ActionRegistration(
        displayName = "#CTL_SwitchToSpecifyRole")
@ActionReference(
        path = "Menu/Window",
        position = 250)
@Messages("CTL_SwitchToSpecifyRole=Switch to Specify Role")
public final class SwitchToSpecifyRole implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {
      WindowManager.getDefault().setRole("specify");
    }

}

You now have a controler mechanism, defined by a set of actions, invoked from menu items in the Window menu, for switching between roles.

workflow 72 new canvas 6

You also have an installer class which sets the initial role in the application.

Creating a Window Based Controler Mechanism

In this section, you create a new window to control switching between canvases.

In the Control module, create a new TopComponent , with WorkflowControl as the class name prefix. Add a dependency on the File System API and define the constructor of the TopComponent as follows. Also make sure that the "category" of each ActionListener defined in the previous section is set to "Predict".

public WorkflowControlTopComponent() {
    initComponents();
    setName(Bundle.CTL_WorkflowControlTopComponent());
    setToolTipText(Bundle.HINT_WorkflowControlTopComponent());
    setLayout(new FlowLayout(FlowLayout.LEFT, 14, 10));
    for (FileObject fo : FileUtil.getConfigFile("Actions/Predict").getChildren()) {
        Action action = FileUtil.getConfigObject(fo.getPath(), Action.class);
        JButton button = new JButton(action);
        button.setPreferredSize(new Dimension(150,100));
        add(button);
    }
}

You now have a controler mechanism, defined by a set of buttons in a TopComponent for switching between roles.

workflow 72 new control 4

You also have an installer class which sets the initial role in the application.

The tutorial is complete. You have created a modular application on the NetBeans Platform, providing the infrastructure for a workflow application.