LSPS documentation logo
LSPS Documentation
Agile Processes

Required result: A model that is restartable and allows the user to move between tasks arbitrarily:

  • When the adminstrator restarts the model instance, the model instance will recover its original progress based on persisted data.
  • When the user can move to any task in the workflow.

Note: You can download an example implementation here. To import the model, do the following:

  1. Create a GO-BPMN project.
  2. Right-click the project and select Import > Archive file.
  3. Enter the path to the zip file into the From archive file field.
  4. Click Finish.

Patterns of agile mechanisms solve the following:

  • Set the correct execution state after restart: on restart, the process omits activities that were already performed.

    For example, if you interrupted an order-dispatch process at a moment when the order is ready to be dispatched, on restart, the process omits the invoicing and payment activities and proceeds to the dispatch activity.

    This also allows you to update the underlying model easily: you stop your model instances, upload a new version of the model, and resume the stopped model instance according to the new model. The new model instance get into the same or equivalent execution status as the original model instance on resume.

  • Skip arbitrarily through activities: skipping is used to implement such features as breadcrumb navigation; the user can switch between activities freely. On switch, the process deactivates the current activity and activates another.

The pattern is as follows:

  • Each "skippable" flow sequence is implemented as a process or a task type: the sequence has the activity reflection type enabled so it can be triggered by the Execute task.
  • The sequence is executed by an Execute task of a wrapper process, which wraps the Execute task in the skipping mechanism.
  • The wrapper process takes a parameter with the current step: if the current step does not correspond to the required step, the Execute task is not executed.
  • The wrapper process is called as a subprocess from an orchestrating main process.
  • If the skippable flow sequence signalizes that it should be deactivated, the Executable task handles the signalization, deactivates the wrapper process and activates another wrapper process.

Base

We will create a process that will represents one step of our process: The step will be then used multiple times in a main process in a series of Reusable Subprocesses. We will design the omitting and skipping mechanisms in the step process.

  1. Design the subprocess:
    1. Create a BPMN-based process called step.
    2. Unselect the Instantiate Automatically option in the process properties: If you leave the option selected, a bogus instances of the step process would be created every time we instantiate the main process. Also, it would not be possible to define parameters for the process.
    3. Define the process parameters: these should provide data for the activity of the step.

      For example, use the User task and design for it a form with a submit button.

  2. Design the coordinating parent process:
    1. Create process definition with a BPMN-based process; name it flow.
    2. In the flow process, create a flow of Reusable Processes with the step process.
      agile_collaterals_process.png
  3. You now have a working model: run it and check that the process instance has one step sub-Processes running at a time and that the step sub-process is not instantiated as its own process instance.
    agile_prerequisite.png
    Model instance details of a successful run

Skipping

The skip mechanism allows you to restart your model instances at any point without having to worry about data consistency or flow interruptions.

To implement it, we will make the flow process send data on whether the step process needs to execute its Activity to the step process. The value of the data should depend on persisted data so it remains unchanged in case of model instance restart. However, we will use a global variable to store the data to keep it simple.

Goal: Create the skipping mechanism inside step around its Task and make the flow send the omitCondition value to step.

  1. In the step process, design the evaluation of the condition:
    1. Define the omitCondition parameter of type Boolean: the parameter will be sent by the parent process.
    2. Around the step task, design the workflow that will avoid the Activity when the omitCondition will be true.
      agile_omitting_subprocess.png
    3. Make the flow pointing to the activity the default flow.
  2. Create a global Integer variable lastSuccessfulStep with initial value 0: it represents the last successfully executed step process.
  3. In the flow process, pass the condition based on the last successful step as the omitCondition argument to each Reusable Process.
    • on the first Reusable Subprocess omitCondition -> lastSuccessfulStep >= 1 (When the last successful step equals or is larger than 1, the condition is true.)
    • on the second Reusable Subprocess omitCondition -> lastSuccessfulStep >= 2 (When the last successful step equals or is larger than 2, the condition is true.)
  4. Test the process, set the initial value of lastSuccessfulStep to a value (0, 1, and 2) and run a model instance with the value. Check the behavior of the subprocesses: make sure the skipping works as expected.
agile_omitting_testrun.png
Run with lastSuccessfulStep set to 1. The subprocess that used the omitting flow displayed below.
Points to Consider

  • While here you are omitting the same task over and over again, in real world scenarios, you will omit different types of Activities:

    Change the type of the User task in the step sub-process to the Executable task type and pass the user task in the activity parameter of the sub-process along with the condition parameter.

  • To evaluate the conditions for omitting, do not use global variables: use data persisted in the database.

Deactivation

The deactivation mechanism terminates the current sub-process instance under specific circumstances. It could be either when it receives a signal or when a condition becomes true.

We will use a Signal: To the Task in the step process, we will attach an interrupting Catch Signal Intermediate Event. It will wait for the Task to throw a Signal: when this happens, the Signal Intermediate Event will be activated and the Task deactivated. The execution will take the outgoing flow of the event, which will enter a No Exit End Event. The end event will terminate the sub-process instance without letting the subprocess produce a token: this will prevent the parent process from continuing its execution.

To design the deactivation mechanism, do the following:

  1. Adapt the Task in the step process so it throws a Signal; for example, if you are using a User task, add to its form a Deactivate button, which calls sendSignal(false, {thisModelInstance()}, "deactivate") when clicked.
  2. Adapt the step so it finishes when it receives a Signal:
    1. Add an interrupting Intermediate Catch Signal Event to the boundary of the Task.
    2. Set the filter to { r:Object -> true}) so it catches any Signal.
    3. Connect the event to a No Exit End Event:

      The No Exit End event ends the execution flow of the reusable sub-process just like Simple End Event. Unlike Simple End Event, it prevents the execution to continue out of the Subprocess: The Subprocess does not produce a token.

      agile_deactivation_subprocess.png
  3. In the flow process, change the Reusable Subprocesses to Inline Event Subprocess.

    Inline Event Subprocesses are considered a part of the parent process, that is, the flow process. They are instantiated as process instances while non-inline-event subprocesses create subprocess instances. Only Inline Event Subprocesses can finish with a No Exit Event.

    agile_deactivation_process_inlinesp.png
  4. Run the model and deactivate it in one of the steps.
    agile_deactivation_testrun.png
    Model instance deactivated in the first subprocess. The diagram with the activity deactivated by the Catch Signal Event is below.

Summary

You have implemented the following behavior:

  1. The User Task or another Activity of the step process can throw a Signal.
  2. When this happens, the Catch Signal Intermediate Event catches the signal and terminates the Activity.
  3. The outgoing flow of the Catch Signal Intermediate Event is taken.
  4. The No Exit Event end is executed: The step subprocess instance finishes.
  5. The flow process instance finishes since no sub-process instance is running.
  6. The model instance is deactivated.

Activation

The model can now omit already performed Activities and deactivate their step processes. Now you need to let the flow process activate the correct step when another step is deactivated. You will pass the information to the step process as a parameter in the deactivation Signal:

  1. Add the id Integer parameter to step so you can identify the step to activate. The parameter will be populated by the flow process depending on the position of the Reusable Process in the flow and hold the step that should be activated upon deactivation.
    agile_collaterals_subprocess.png
  2. Add the information on which step should be activated upon deactivation to the deactivation Signal you are sending from your Task:
    sendSignal(false, {thisModelInstance()}, goto)`
    If you are using a User Task as your activity, rename the Deactivate button to Go To Activity and navigate away from the to-do, when the user clicks it so the user is not stuck on a page with the to-do of the deactivated task.
  3. Still in the step process, add the Signal Start Event

    Since step is an Inline Event Subprocess, all Signal Start Events in all steps will be listening for a Signal and can be activated when a Signal is received.

  4. Define the Signal Start Event filter so the step process is activated only if its id parameter set by flow matches the goto parameter sent in the Signal: { activateStep:Integer -> activateStep == id }
    agile_activation_subprocess.png
  5. In the flow process, add the id parameter value to the reusable sub-processes and the goto parameter.
    agile_deactivation_process_param.png
  6. Run the model.
    agile_finaltest.png
    Points to Consider
  • Typically, you will skip to a step based on input provided by a user in a to-do: in such a case, you will need to adapt the respective form so it passes the go-to data: a listener could send the signal with a goto value from an input field.