Skip to main content

Getting Started with Process Automation

The process automation component is designed to gradually increase complexity when needed. This guide will take you through the most common functionality of the component and set you up to tackle more advanced use-cases later.

More extensive documentation on these steps can be found in the Reference Guides: General Overview

Prerequisites​

This guide assumes some (basic) prior knowledge. It is advised to read up on these topics if they are not immediately clear yet.

  • Component model: We will extend the Component model with Workflows.
  • Finite state machines: Processing is modeled using state machines. We will refer to state machine terminology such as state and transition.

Installing the component​

When using workflow component

If you are already using the workflow component, make sure to migrate it first. Go to migration guide.

The first step is to add the component to your applicationApplicationThe overarching model container grouping all components, domain logic, and configurations for an enterprise solution.. We start by adding the process-automation-component expansion resourceExpansion Resource (ExpansionResource). A reusable resource bundle containing expanders and features that provide specific application capabilities, defined in the expansion settings and added to the classpath during expansion.. Additionally, you may want to add the process-automation-tracing expansion resourceExpansion Resource (ExpansionResource). A reusable resource bundle containing expanders and features that provide specific application capabilities, defined in the expansion settings and added to the classpath during expansion.. This will add a log statement for every executed transition within your applicationApplicationThe overarching model container grouping all components, domain logic, and configurations for an enterprise solution..

  1. Navigate to settings > expansionResources.
  2. Add a row with name {processAutomation.groupId}:{processAutomation.artifactId} and version {processAutomation.version}.
  3. (Optional) Add a row with name {processAutomationTracing.groupId}:{processAutomationTracing.artifactId} and version {processAutomationTracing.version}.

Finally, we need to add the component itself into the applicationApplicationThe overarching model container grouping all components, domain logic, and configurations for an enterprise solution. model. Add processAutomation to the applicationApplicationThe overarching model container grouping all components, domain logic, and configurations for an enterprise solution. components and don't forget to add processAutomation as a component dependency to the components that will use it as well.

Creating a workflow​

We will mostly be working with the Workflow model, which is an extension of Component. This means it lives next to (and not inside) DataElement and TaskElement. Each workflow defines a single state machine. Most applicationsApplicationThe overarching model container grouping all components, domain logic, and configurations for an enterprise solution. are too complex to put into a single state-machine, which is why multiple state machines can run in parallel.

Selecting a target​

The state within our state machine needs to be stored somewhere. Since we already model data using DataElements, we will use these as a target for workflows. A String fieldFieldA property of a DataElement expanded to a database column and user interface input element. is added to a known DataElement to maintain the active state of a specific DataElement instance.

  1. Navigate to your Component.
  2. In the tree-view, open the context menu of the target DataElement (right-click).
  3. Select "Create workflow environment". This will create a «DataElement»Flow workflow element.

Marking the initial state​

A workflow defines a set of states, which lists all possible states in our state-machine. Each state has a name property to make it easier when reasoning about a workflow. Additionally one state can be marked as the initial state. As a result of defining the initial state, every instance from the targeted DataElement will start with a status value equal to the name of the initial state. This value is set in the pre-create anchorAnchorA marker within generated source code reserved for adding custom logic during re-expansion. on the «DataElement»Bean.

  1. In the tree-view, open the context menu of the Workflow (right-click).
  2. Select "New State". This will open the edit screen of a new state.
  3. Give the state a name and enable the initialState checkbox to mark it as initial state.
  4. Click 'Create'.
caution

A state machine should always have exactly one initial state. Read the documentation on initial states to see how having multiple initial states can be prevented.

Adding Transitions​

Now that we have the basic elements in place, it is time to add functionality. We define transitions to model functionality within a workflow. Creating a transition is similar to crating a state, but we will have to enter the related states.

You may notice the end state to be defined in a list of endStates, we will discuss this further in Branching tasks.

Before creating a transition, it is advised to have a begin and end state already present. For interim and failed state the µRadiant provides a generator.

  1. In the tree-view, open the context menu of the Workflow (right-click).
  2. Select "New Transition". This will open the edit screen of a new state.
  3. Give the transition a name and select the beginState from the provided dropdown.
  4. (Optional) Explicitly select an interim and/or failed state, these are generated otherwise.
  5. Click " New workflows::EndState::model" under endStates
  6. Select a state from the dropdown in the newly created row. Leave taskOutcome empty.
  7. Click 'Create'.

Executing tasks​

Now that we can define the stateful lifecycle of a dataElement, it is time to perform some actual work! We already model each unit of work as a TaskElement which makes it a good candidate for integration with workflows. To execute a task within a transition, simply configure the task as executeTask fieldFieldA property of a DataElement expanded to a database column and user interface input element. on the transition.

One thing to consider is the that the targetField on a workflow must be from the same DataElement as the TaskElement targetElement. The task will contain any business logic needed for the transition.

Branching tasks​

With tasks as discussed so far it is already possible to model many use-cases for a workflow. By introducing branching the model can become even more expressive. A TaskElement allows you to define a set of TaskOutcomes. Each outcome can then be interpreted by a transition in order to determine the correct end state. Consider the example of Schrödingers cat and a task to open the box.

Since the TaskOutcomes are decoupled from the resulting state, it is possible to re-use (branching) Tasks in multiple transitions.

Adding a TaskOutcome to the TaskElement (repeatable):

  1. In the tree-view, open the context menu of the Task (right-click).
  2. Select "New TaskOutcome". This will open the edit screen of a new outcome.
  3. Give the outcome a name and optionally a description.
  4. Click 'Create'

Defining endStates on a Transition with TaskOutcomes

  1. In the tree-view, find and select the Transition (left-click).
  2. Under endStates, add as many rows as you need to fit all outcomes.
  3. In each row, select an outcome from the taskOutcome dropdown and an end state from the state dropdown.

Modeling behavior​

So far we've only discussed what our applicationApplicationThe overarching model container grouping all components, domain logic, and configurations for an enterprise solution. should be doing, but we are missing when this should be done. The workflow model has the concept of Triggers which model the behavior of transitions. Process automation ships with several useful triggers out of the box: OnCreate, OnModify, OnTransition, ByDataCommand, Schedule and FlowEngine.

Creating triggers is very similar regardless of its type.

  1. In the tree-view, open the context menu of the Transition (right-click).
  2. Select "New <trigger>" where <trigger> is the desired trigger. This will open the edit screen of a new Trigger.
  3. Configure the trigger. Most triggers only need a name, others will be described more in the coming sections.
  4. Click 'Create'

The only trigger that demands extra effort is the ByDataCommand trigger.

In order for this to work, we first need to define a dataCommand. This command has two important options to customize behavior. By default, the command will only schedule the transition and return immediately. To make the command wait while transitioning, the workflow.trigger.blockingMs option can be either set to a positive integer (the timeout) or to the value until_complete (no timeout). The options workflow.trigger.button can be used to conveniently add a button to the knockout UI, if present in your applicationApplicationThe overarching model container grouping all components, domain logic, and configurations for an enterprise solution..

  1. In the tree-view, open the context menu of the DataElement (right-click).
  2. Select "New DataCommand". This will open the edit screen of a new DataCommand.
  3. Name the dataCommand and check 'hasTargetInstance'.
  4. (Optional) Add workflow.trigger.button and workflow.trigger.blockingMs options for additional configuration.
  5. Click 'Create'
  6. The newly created dataCommand can now be selected as the dataCommand when creating a ByDataCommand trigger.
tip

The ByDataCommand trigger is an abstraction well suited for integration-testing workflow transitions. Its independence on time or other (uncontrollable) events makes it great for swift testing without working around stateful execution.

Transition recovery​

It is possible a transition cannot complete successfully. As a result a DataElement may be stuck in an interim state. To resolve this issue process automation attempts a recovery procedure at startup. The default behavior is to move to the failed state.

Recovery state​

Alternatively, the recovery state can explicitly be configured on the Transition. Simply select a recovery state from the dropdown to configure it as the state to be used when recovering the transition.

  1. In the tree-view, find and select the Transition (left-click).
  2. Select the recoveryState from the dropdown or leave it empty to use the default.

Transactions​

It is possible to use the begin state as the recovery state with one restriction. The executed task must be transactional. In order for recovery to the begin state to be valid, the task must not have performed any side effects. Having a transaction around a task at least ensures there were no database modifications as a result of a failed task.

Note

You still need to make sure no other side effects were performed within the task. For example when making a request to an external api, a compensating request may be needed in order to cancel the initial request.