Techies.

SpringBot Custom Workflow Logic

Learn how to add in custom logic to your workflow in SpringBot. From triggering actions to updating entity details, you can customise it however you require.


As with all behaviours, you will occasionally have a need to create custom actions which aren’t available in the standard behaviour. When it comes to Workflow, this will often manifest as a need to trigger actions or results when a workflow state changes. The bots enable you to do this by allowing you to add custom logic into the server-side.

Getting Started

When a workflow state is selected or updated, the application treats this like normal entity update. Therefore, we can simply put our custom logic inside the listener which actions before the entity update is persisted into the database.

Updating Workflow State

By default, every entity has an accompanying listener, normally accurately named along the lines of <Entity Name>EntityListener (e.g. FishEntityListener for the Fish entity). Listeners are a form of hooks which allow developers to tap into the entity at various stages of its lifecycle. All listeners are placed inside <domain name>/listeners, with domain name being the reversed domain URL of the site (e.g. com/fishnatics/listeners for the Fishnatics app).

The first step is to open the appropriate listener.

In the listener, the provided entity parameter represents the newest state of the entity (i.e. the entity’s new state after progressing it through the workflow). Turn on the protected region Add any custom logic to be executed before the entity is updated here so you can add your custom logic against that new workflow state.

To obtain an entity’s workflow states, use entity.getWorkflowStates(). This will return all of workflow states that this entity holds. To find the workflow you’re looking for, we need to filter these states using the following code:

WorkflowVersionEntity workflow = entity
        .getWorkflowStates()
        .stream()
        .map(WorkflowStateEntity::getWorkflowVersion)
        .filter(workflowVersion -> /* Custom filtering logic here */)
        .findFirst();

Once you have obtained the workflow version entity, you can add your own custom logic.

Example Scenario

Let’s say that we have the following scenario:

  • An Entity called Tank with a workflow behaviour Cleaning Process and a date attribute called Last Cleaned.
  • The workflow Cleaning Process has two states Dirty and Clean.

Now let’s say that we want to implement some custom logic: when a Tank’s Cleaning Process state changes from Dirty to Clean, we want to update the Last Cleaned attribute.

First, we need some imports. Turn on the protected region Add any additional imports here and insert the following code:

import <domain name>.entities.WorkflowVersionEntity;
import <domain name>.entities.WorkflowStateEntity;
import java.time.OffsetDateTime;

Note that domain name varies between different applications.

Now, we are following the steps outlined in the Updating Workflow State section. Turn on the protected region Add any custom logic to be executed before the entity is updated here and insert the following code:

// Retrieve the state for the Cleaning Process workflow.
WorkflowStateEntity state = entity
        .getWorkflowStates()
        .stream()
        .filter(s -> {
            WorkflowVersionEntity version = s.getWorkflowVersion();
            return version.getWorkflowName().equals("Cleaning Process");
        })
        .findFirst()
        .orElseThrow();

// If our state is updated to `Clean`, proceed with our custom logic.
if (state.getStepName().equals("Clean")) {
    entity.setLastCleaned(OffsetDateTime.now());
}

In this code we retrieve the new state of the Cleaning Process workflow and assign it to the state variable. Next we simply do a quick check to see if the new state is Clean, and then set the last cleaned attribute to today’s date.

Last updated: 15 January 2020


Related articles