Documentation Index
Fetch the complete documentation index at: https://docs.activeviam.com/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Once the task has been submitted on the Atoti Sign-Off UI, the details are sent to the Atoti Sign-Off server, where the action is completed by the IWorkflowTaskActionDelegator. This delegator accepts the submitted WorkflowTaskActionExecutionDTO, then delegates and
executes the task as required.
The submitted DTO
The WorkflowTaskActionExecutionDTO object looks as follows:
import java.io.Serializable;
public class WorkflowTaskActionExecutionDTO implements Serializable {
private static final long serialVersionUID = 6548671478152737730L;
// The key of the task to be executed
protected String taskKey;
// The type of workflow. Either DEFINITION or TASK
protected String workflowType;
// The object keys (process definition ID or task ID) for which to process the task action.
protected List<String> keys = new ArrayList<>();
// Optional workflow variables to provide in the DTO
protected Map<String, Serializable> taskVariables = new HashMap<>();
}
where:
- the
taskKey is used by the delegator to determine which task to execute.
- the
workflowType indicates the type of workflow the action belongs to.
- the
keys indicate the objects upon which the action is executed.
- the
taskVariables store optional task variables to be handled by the backend and are the result of the inputs to the WorkflowTaskActionInputFieldDTO.
The delegator
The IWorkflowTaskActionDelegator is a simple delegator that accepts a WorkflowTaskActionExecutionDTO and delegates the work to a backend service. It contains one method:
/**
* <b>IWorkflowTaskActionDelegator</b>
*
* <p>A delegator which accepts a {@link WorkflowTaskActionExecutionDTO}, which contains a {@code
* taskKey}, and resolves that key to a task action.
*
* @author ActiveViam
*/
public interface IWorkflowTaskActionDelegator {
/**
* This initiates a workflow task action related to the button the user selected. This function
* will have to be updated for every new button.
*
* @param workflowTaskActionExecutionDTO the payload to execute an action
*/
void executeTaskAction(WorkflowTaskActionExecutionDTO workflowTaskActionExecutionDTO) throws ValidationException;
}
The executeTaskAction() method accepts the WorkflowTaskActionExecutionDTO and delegates it to a task action based on its taskKey.
Customize the Java tasks
The delegator has a custom implementation defined. This can be overridden if you’re not using the out-of-the-box workflows.
Alternatively, you can append custom actions to the default implementation by implementing the ICustomWorkflowTaskActionService.
The default delegator
The default delegator is implemented in DefaultWorkflowTaskActionDelegator, which is imported in the starter.
Take a look to see how the tasks are delegated, but note that the methods of delegation are completely up to you.
Override the default delegator
To override the delegator, implement your own IWorkflowTaskActionDelegator.
Here’s an example of a simple delegator that logs the action that is executed:
@Component
@Slf4j
public class LogWorkflowTaskActionDelegator implements IWorkflowTaskActionDelegator {
@Override
public void executeTaskAction(WorkflowTaskActionExecutionDTO workflowTaskActionExecutionDTO)
throws ValidationException {
log.info("Executing task for key {}", workflowTaskActionExecutionDTO.getTaskKey());
if (workflowTaskActionExecutionDTO.getWorkflowType() == "MY_WORKFLOW_TYPE") {
switch (workflowTaskActionExecutionDTO.getTaskKey()) {
case "MY_ACTION_1":
// Execution for action 1 ...
break;
}
}
}
}
You then may implement different logic for different combinations of workflow types and task keys retrieved from the WorkflowTaskActionExecutionDTO object.
Append to the default delegator
To append to the default delegator, add an implementation of ICustomWorkflowTaskActionService.
The ICustomWorkflowTaskActionService has one method that needs to be overridden: executeCustomTask(). This method is responsible for managing how the task is executed in the backend.
public interface ICustomWorkflowTaskActionService {
/**
* @param workflowTaskActionExecutionDTO - the custom workflow task action to execute
*/
void executeCustomTask(WorkflowTaskActionExecutionDTO workflowTaskActionExecutionDTO);
}
If a task key is provided that is not currently handled, it will eventually be routed to the ICustomWorkflowTaskActionService and the default implementation in the starter will throw an exception:@Slf4j
@Service
public class DefaultCustomWorkflowTaskActionService implements ICustomWorkflowTaskActionService {
private final static String ERROR_MSG =
"No workflow action found for taskKey %s. "
+ "If this is a custom workflow action then please implement your own ICustomWorkflowTaskActionService to handle it.";
@Override
public UserTaskRecordDTO executeCustomTask(WorkflowTaskActionExecutionDTO workflowTaskActionExecutionDTO) {
String message =
String.format(ERROR_MSG, workflowTaskActionExecutionDTO.getTaskKey());
throw new ActiveViamRuntimeException(message);
}
}
Here’s an example of a custom comment action:
@Service
@RequiredArgsConstructor
@Slf4j
public class ExampleCustomWorkflowTaskActionService implements ICustomWorkflowTaskActionService{
public static final String COMMENT_KEY = "CUSTOM COMMENT";
protected ISignOffProcessInstanceWorkflowService signOffProcessInstanceWorkflowService;
protected ISignOffProcessDefinitionWorkflowService signOffProcessDefinitionWorkflowService;
@Override
public List<AHistoryRecordDTO> executeCustomTask(WorkflowTaskActionExecutionDTO executionDTO) {
List<AHistoryRecordDTO> historyRecordDTOS = new ArrayList<>();
Map<String, String> variables = executionDTO.getTaskVariables();
if (executionDTO.getTaskKey().equals(COMMENT_KEY)) {
try {
for (String key: executionDTO.getKeys()) {
historyRecordDTOS.add(executeCommentTask(key, variables, executionDTO.getWorkflowType()));
}
} catch (ValidationException e) {
throw new ActiveViamRuntimeException(e);
}
} else {
log.error("No custom task action configured for key {}", executionDTO.getTaskKey());
}
return historyRecordDTOS;
}
private UserTaskRecordDTO executeCommentTask(String key, Map<String, String> variables, String workflowType) throws ValidationException {
UserTaskRecordDTO userTaskRecordDTO = null;
switch (workflowType) {
case DEFINITION_WORKFLOW_TYPE -> userTaskRecordDTO = commentOnDefinition(key, variables);
case TASK_WORKFLOW_TYPE -> userTaskRecordDTO = commentOnTask(key, variables);
default -> log.error("Unknown workflow type {}", workflowType);
}
return userTaskRecordDTO;
}
private UserTaskRecordDTO commentOnDefinition(String key, Map<String, String> workflowVariables) throws ValidationException {
SignOffProcessDefinitionDTO definitionDTO = signOffProcessDefinitionWorkflowService.get(key);
Map<String, Object> variables = new HashMap<>();
variables.put("action", "comment");
variables.putAll(workflowVariables);
return signOffProcessDefinitionWorkflowService.taskStateTransition(key, definitionDTO, COMMENT_KEY, "Commenting", variables);
}
private UserTaskRecordDTO commentOnTask(String key, Map<String, String> workflowVariables) throws ValidationException {
SignOffProcessInstanceDTO taskDTO = signOffProcessInstanceWorkflowService.get(key);
Map<String, Object> variables = new HashMap<>();
variables.put("action", "comment");
variables.putAll(workflowVariables);
return signOffProcessInstanceWorkflowService.taskStateTransition(key, taskDTO, COMMENT_KEY, "Commenting", variables);
}
}
Note that unlike actions defined in the DefaultWorkflowTaskActionDelegator.java this implements a logic that fits both workflow types.
Import the services
Once the appropriate components/services have been defined, import them to the project using a Spring configuration class.