Defining Task Spring Beans

Overview

The class WorkflowTaskActionDTO is used to represent a custom workflow task action.

@Data
@SuperBuilder(toBuilder = true)
@NoArgsConstructor
public class WorkflowTaskActionDTO implements Serializable {

    // The name of the task action, which will appear as the button.
    protected String name;
    // The task key of the custom action. This is used to trigger an action in the backend, and should be unique for each task action in the application.
    protected String taskKey;
    // The css style of the button (unused for now).
    protected String style;

    // True if the button should be enabled, false otherwise.
    @Builder.Default
    protected boolean enabled = true;

    // Input fields for workflow action. Used by the UI to generate component on-the-fly.
    protected List<WorkflowTaskActionInputFieldDTO> taskInputFields;

    /**
     * An optional consumer to update a value of the DTO (for example if the button is enabled) that accepts the
     * current {@link UserTask} and the {@link LimitsProcessInstance} to provide current information when querying the DTOs.
     * See {@link LimitsActivitiService#extractWorkflowActionsFromUserTask }.
     * */
    @Builder.Default
    @JsonIgnore
    protected TriConsumer<WorkflowTaskActionDTO, UserTask, LimitsProcessInstance> currentTaskConsumer = (wa, ut, lpi) -> {
    };
}

The class WorkflowTaskActionInputFieldDTO is defined as:

@Data
@SuperBuilder(toBuilder = true)
public class WorkflowTaskActionInputFieldDTO {

    // The label of the UI field.
    protected String label;
    // The task variable used to link this input field with a backend variable.
    protected String taskVariable;
    // The input type of this field: SELECT for multiple options (a dropdown), TEST for a text input.
    protected WorkflowTaskActionInputFieldInputType inputType;
    // If this field is required by the UI for form submission.
    protected boolean required;
    // The list of options for a SELECT field. Will not be used for TEXT fields.
    @Builder.Default protected List<String> options = new ArrayList<>();
    // A value to pre-fill the input field with.
    protected String defaultValue;
}

where WorkflowTaskActionInputFieldInputType can be one of:

public enum WorkflowTaskActionInputFieldInputType {
    SELECT, // Select multiple options from a dropdown.
    TEXT, // Input the option as a text field.
    LINK // Input the option as a navigable link.
}

We have added lombok builder methods to quickly create instances of this class.

Defining the Beans

Depending on the type of WorkflowTaskActionDTO supplied to the UI, it will render a button that on clicking will either:

  • Execute an action
  • Show a popup for submission and then execute an action

1. Execution only action

The simplest instance of a WorkflowTaskActionDTO will look as follows:

    @Bean
    public WorkflowTaskActionDTO approveTaskButtonWorkflowAction(){
            return WorkflowTaskActionDTO.builder()
                .name("Approve")
                .taskKey("APPROVED")
                .build();
    }

In this case, a button will appear on the UI with the label Approve and when clicked, it will submit a response to the server to execute the task specified by the task key “APPROVED”. For more information on how the task is executed see Executing the Java Task.

2. Popup with execution action

A more complex instance of a WorkflowTaskActionDTO will specify input fields to be rendered in the UI, updated and submitted to the server. It can also provide an defaultValue for fields, which will pre-populate the input field in the UI. Example:

    @Bean
    public WorkflowActionDTO reviewBreachTaskButtonWorkflowAction(){
            List<WorkflowTaskActionInputFieldDTO> inputFields = new ArrayList<>();
            WorkflowTaskActionInputFieldDTO classificationField = WorkflowTaskActionInputFieldDTO.builder()
                .label("Classification")
                .taskVariable("classification")
                .required(true)
                .inputType(SELECT)
                .options(List.of("Unclassified","Technical Issue","True Breach","New Trade","Late Trade","Market Moved"))
                .defaultValue("Unclassified")
                .build();
    
            WorkflowTaskActionInputFieldDTO riskCommentField = WorkflowTaskActionInputFieldDTO.builder()
                .label("Risk comment")
                .taskVariable("riskComment")
                .inputType(TEXT)
                .build();
    
            inputFields.add(classificationField);
            inputFields.add(riskCommentField);
    
            return WorkflowTaskActionDTO.builder()
                .name(REVIEW_NAME)
                .taskKey(REVIEW_KEY)
                .taskInputFields(inputFields)
                .build();
        }

In this example, we define two input fields: Classification and Risk Comment, with the following properties:

  • Classification is required, so the form may not be submitted until its value is filled. Risk Comment is not specified as required, so it defaults to false.
  • Classification has input type SELECT, so the options listed will be available in a dropdown.
  • Risk Comment has input type TEXT, so a text field will appear requesting input.

Importing the Beans

Once defined, the beans can then be imported into the Atoti Limits project. A nice convention is to have one @Configuration file per workflow, and to import these into a parent @Configuration. Then, this one parent @Configuration can be imported to the project.

For example, the out-of-the-box workflow actions are included in WorkflowTaskActionsConfig:

@Import({
        // Out-of-the-box workflows
        FourEyesWorkflowTaskActionsConfig.class,
        ExceptionWorkflowTaskActionsConfig.class
})
@Configuration
public class WorkflowTaskActionsConfig {

}
  • and the FourEyesWorkflowTaskActionConfig class contains the tasks related to the four eyes workflow:
@Configuration
public class FourEyesWorkflowTaskActionsConfig {

    @Autowired
    protected LimitsProcessInstanceWorkflowService limitsProcessInstanceWorkflowService;

    @Bean
    public WorkflowTaskActionDTO approveButtonWorkflowAction() {
        return WorkflowTaskActionDTO.builder()
                .name(APPROVED_NAME)
                .taskKey(APPROVED_KEY)
                .currentTaskConsumer(createCurrentUserApprovalConsumer())
                .build();
    }
    
    // ....other action beans
}