Package com.veeva.vault.sdk.api.workflow


package com.veeva.vault.sdk.api.workflow
This package provides interfaces to create custom actions for workflows, initiate workflow actions, and update entities within workflow processing.

Overview

Using RecordWorkflowAction

Workflows can have custom actions that perform specific instructions. You can use a custom record workflow action to automate certain business processes on an object or document workflow. Document workflows are a type of object workflow configured on the envelope__sys object. If you are unfamiliar with object or document workflows, you should learn more in Vault Help before coding a record workflow action:

You can configure a custom action for workflows on any of the following steps:

  • Start step: Actions configured against a participant control which is invoked during start step events. This action can include logic to populate the workflow participants.
  • Task step: Actions which are automatically invoked when a workflow task reaches a specified task event. Learn more about available events in WorkflowEvent.

A record workflow action is a Java class that implements the RecordWorkflowAction interface and has the @RecordWorkflowActionInfo annotation. The @RecordWorkflowActionInfo annotation has the following elements:

  • label: Label of the action
  • object: If specified, the action is only available for object workflows associated to the specified object. If omitted, the action is available across all object workflows.
  • stepTypes: The workflow step types that this action can be configured against.

Example: Record Workflow Action on a Start Step

The following example illustrates a custom action available for configuration on the Start step of an object workflow configured for the Product object. Once configured on an object workflow's start step participant control, the action will be invoked on all start step events during workflow execution.

This example executes custom logic on the following events:

  • During the DISPLAY_PARTICIPANTS event, this action populates the workflow start dialog with two specific users.
  • During the GET_PARTICIPANTS event, this action populates the participant group for the configured participant control with two specific users.
  • During the AFTER_CREATE event, this action sends a notification to each participant.
 @RecordWorkflowActionInfo(label="Custom Approver", object="product__v", stepTypes={WorkflowStepType.START})
 public class CustomApprover implements RecordWorkflowAction {
          public void execute(RecordWorkflowActionContext context) {
             WorkflowEvent event = context.getEvent();
             WorkflowInstance workflowInstance = context.getWorkflowInstance();

             WorkflowInstanceService workflowInstanceService = ServiceLocator.locate(WorkflowInstanceService.class);
             WorkflowParticipantGroup participantGroup = context.getParticipantGroup();

             //DISPLAY_PARTICIPANTS only shows the users/groups provided by the RecordWorkflowAction. It's not officially saved until GET_PARTICIPANTS.
             //Generally, you would display and save the same users/groups.
             if (event == WorkflowEvent.DISPLAY_PARTICIPANTS || event == WorkflowEvent.GET_PARTICIPANTS) {
                 getParticipants(workflowInstanceService, participantGroup);
             } else if (event == WorkflowEvent.AFTER_CREATE) {
                 afterCreate(workflowInstance, participantGroup);
             }
         }
         private void getParticipants(WorkflowInstanceService workflowInstanceService,
                                      WorkflowParticipantGroup participantGroup) {
             Set<String> users = VaultCollections.newSet();
             users.add("1000000");
             users.add("1000001");
             WorkflowParticipantGroupUpdate participantGroupUpdate =
                     workflowInstanceService.newParticipantGroupUpdate(participantGroup)
                             .setUsers(users);
             workflowInstanceService.updateParticipantGroup(participantGroupUpdate);
         }
         private void afterCreate(WorkflowInstance workflowInstance,
                                  WorkflowParticipantGroup participantGroup) {
             NotificationService notificationService = ServiceLocator.locate(NotificationService.class);

             String processInstanceId = workflowInstance.getId();
             Set<String> participantUserIds = participantGroup.getUsers();
             String participantGroupLabel = participantGroup.getLabel();

             NotificationParameters parameters =
                     notificationService.newNotificationParameters()
                             .setRecipientsByUserIds(participantUserIds);
             String notificationText = "You were added to the participant group \"" + participantGroupLabel
                     + "\" of workflow " + processInstanceId;
             NotificationMessage message =
                     notificationService.newNotificationMessage()
                             .setSubject("A new workflow started")
                             .setMessage(notificationText)
                             .setNotificationText(notificationText);
             notificationService.send(parameters, message);
         }
    }
 
 

Example: Record Workflow Action on a Task Step

The following example illustrates an action that is available for configuration on the Task step of an object workflow configured for the Product object. Once configured on an object workflow's task step, the action will be invoked on all task events for that workflow task step during workflow execution. The code in this example handles task creation, completion dialog, completion, cancellation, and reassignment/acceptance.
  • During the TASK_AFTER_CREATE event, the action logs information for the created task instances.
  • During the TASK_BEFORE_COMPLETE_DIALOG event, the action logs information on the items in the workflow.
  • During the TASK_AFTER_COMPLETE event, the action cancels all other outstanding task instances for the current task step.
  • During the TASK_AFTER_CANCEL event, the action sends a notification to the assignees of each cancelled task instance.
  • During the TASK_AFTER_ASSIGN event, the action logs information for the tasks that have been either reassigned or accepted.
 @RecordWorkflowActionInfo(label="Approver Task Action", object="product__v", stepTypes={WorkflowStepType.TASK})
 public class ApproverTaskAction implements RecordWorkflowAction {
         public void execute(RecordWorkflowActionContext context) {
             WorkflowEvent taskEvent = context.getEvent();
             if (taskEvent == WorkflowEvent.TASK_AFTER_CREATE) {
                 handleCreate(context);
             } else if (taskEvent == WorkflowEvent.TASK_BEFORE_COMPLETE_DIALOG) {
                 handleCompleteDialog(context);
             } else if (taskEvent == WorkflowEvent.TASK_AFTER_COMPLETE) {
                 handleComplete(context);
             } else if (taskEvent == WorkflowEvent.TASK_AFTER_CANCEL) {
                 handleCancel(context);
             } else if (taskEvent == WorkflowEvent.TASK_AFTER_ASSIGN) {
                 handleAssign(context);
             }
         }
         private void handleCreate(RecordWorkflowActionContext context) {
             LogService logger = ServiceLocator.locate(LogService.class);
             RecordWorkflowActionTaskContext taskContext = context.getTaskContext();
             WorkflowTaskConfiguration taskConfiguration = taskContext.getTaskConfiguration();
             String participantGroupLabel = taskConfiguration.getParticipantGroupLabel();

             List<WorkflowTaskChange> createdTaskChanges = taskContext.getTaskChanges();
             logger.info(createdTaskChanges.size() + " tasks have been created for " +
                     "participant group " + participantGroupLabel);

             for (WorkflowTaskChange taskChange : createdTaskChanges) {
                 WorkflowTaskInstance createdTaskInstance = taskChange.getNew();
                 String taskId = createdTaskInstance.getId();
                 String assigneeId = createdTaskInstance.getAssigneeId();
                 logger.info("Task " + taskId + " has been created for user " + assigneeId);
             }
         }
         private void handleCompleteDialog(RecordWorkflowActionContext context) {
             LogService logger = ServiceLocator.locate(LogService.class);
             logger.info("[Task before complete dialog] The current workflow has the following items: ");
             List<WorkflowItem> workflowItems = context.getWorkflowItems();
             for(WorkflowItem item : workflowItems) {
                 if(item.getWorkflowItemType() == WorkflowItemType.RECORD) {
                     WorkflowItemRecord record = item.getTypedWorkflowItem(WorkflowItemRecord.class);
                     logger.info("Record: {}.{}", record.getObjectName(), record.getRecordId());
                 } else if(item.getWorkflowItemType() == WorkflowItemType.DOCUMENT) {
                     WorkflowItemDocument document = item.getTypedWorkflowItem(WorkflowItemDocument.class);
                     logger.info("Document Version: {}_{}_{}", document.getId(), document.getMajorVersion(), document.getMinorVersion());
                 }
             }
         }
         private void handleComplete(RecordWorkflowActionContext context) {
             WorkflowTaskService workflowTaskService = ServiceLocator.locate(WorkflowTaskService.class);
             WorkflowInstance workflowInstance = context.getWorkflowInstance();
             RecordWorkflowActionTaskContext taskContext = context.getTaskContext();
             WorkflowTaskConfiguration taskConfiguration = taskContext.getTaskConfiguration();
             WorkflowTaskInstance completedTaskInstance = taskContext.getTaskChanges().get(0).getNew();

             // Find all outstanding task instances (assigned or available) for the current task step
             WorkflowTaskQueryParameters queryParameters = workflowTaskService.newWorkflowTaskQueryParameters()
                     .setStatuses(WorkflowTaskStatus.ASSIGNED, WorkflowTaskStatus.AVAILABLE)
                     .setTaskConfigurations(taskConfiguration);
             List<WorkflowTaskInstance> openTaskInstancesForTask =
                     workflowTaskService.getTaskInstances(workflowInstance, queryParameters);

             // Cancel all other outstanding task instances for the current task step
             List<WorkflowTaskInstance> tasksToCancel = VaultCollections.newList();
             for (WorkflowTaskInstance taskInstance : openTaskInstancesForTask) {
                 if (!taskInstance.getId().equals(completedTaskInstance.getId())) {
                     tasksToCancel.add(taskInstance);
                 }
             }
             if (!tasksToCancel.isEmpty()) { workflowTaskService.cancel(workflowInstance, tasksToCancel); }
         }
         private void handleCancel(RecordWorkflowActionContext context) {
             RecordWorkflowActionTaskContext taskContext = context.getTaskContext();
             String taskLabel = taskContext.getTaskConfiguration().getLabel();
             List<WorkflowTaskChange> cancelledTaskChanges = taskContext.getTaskChanges();
             String workflowLabel = context.getWorkflowConfiguration().getLabel();

             NotificationService notificationService = ServiceLocator.locate(NotificationService.class);

             Set<String> recipients = VaultCollections.newSet();
             for (WorkflowTaskChange taskChange : cancelledTaskChanges) {
                 WorkflowTaskInstance cancelledTaskInstance = taskChange.getNew();
                 String assigneeId = cancelledTaskInstance.getAssigneeId();
                 recipients.add(assigneeId);
             }

             NotificationParameters parameters =
                     notificationService.newNotificationParameters()
                             .setRecipientsByUserIds(recipients);
             String notificationText = "Task \"" + taskLabel + "\" was cancelled for workflow \"" + workflowLabel + "\".";
             NotificationMessage message =
                     notificationService.newNotificationMessage()
                             .setSubject(notificationText)
                             .setMessage(notificationText)
                             .setNotificationText(notificationText);
             notificationService.send(parameters, message);
         }
         private void handleAssign(RecordWorkflowActionContext context) {
             RecordWorkflowActionTaskContext taskContext = context.getTaskContext();
             WorkflowTaskChange taskChange = taskContext.getTaskChanges().get(0);
             WorkflowTaskInstance newTaskInstance = taskChange.getNew();
             WorkflowTaskInstance oldTaskInstance = taskChange.getOld();
             WorkflowTaskStatus newTaskStatus = newTaskInstance.getStatus();
             WorkflowTaskStatus oldTaskStatus = oldTaskInstance.getStatus();

             String taskId = newTaskInstance.getId();
             String newAssigneeId = newTaskInstance.getAssigneeId();
             String oldAssigneeId = oldTaskInstance.getAssigneeId();

             LogService logger = ServiceLocator.locate(LogService.class);
             if ((oldTaskStatus == WorkflowTaskStatus.ASSIGNED) && (newTaskStatus == WorkflowTaskStatus.ASSIGNED)) {
                 logger.info("Task " + taskId + " has been reassigned from user " + oldAssigneeId + " to " +
                         "user " + newAssigneeId);
             } else if ((oldTaskStatus == WorkflowTaskStatus.AVAILABLE) && (newTaskStatus == WorkflowTaskStatus.ASSIGNED)) {
                 logger.info("Task " + taskId + " has been accepted by user " + newAssigneeId);
             }
         }
    }
 
 

Using WorkflowInstanceService

This service is used to retrieve information about and execute workflow actions. Examples of retrievable information include: active workflow instances, participant groups, available actions on a workflow. Examples of workflow actions include: starting a workflow, cancelling a workflow, adding participants to participant groups.

Example: Starting a Workflow

The following is an example of a starting a workflow with the Vault Java SDK:
 
 // Records to start Workflow with
 String objectName = "object__c";
 String record1 = "V5K000000001001";
 String record2 = "V5K000000001002";
 List<String> records = VaultCollections.asList(record1, record2);  // can also be list of documents if it's a document workflow

 WorkflowMetadataService workflowMetadataService = ServiceLocator.locate(WorkflowMetadataService.class);

 // 1) Get available workflows for given records
 AvailableWorkflowMetadataCollectionRequest availableWorkflowsRequest = workflowMetadataService.newAvailableWorkflowMetadataCollectionRequestBuilder()
                                                                 .withRecords(objectName, records)
                                                                 .build();

 AvailableWorkflowMetadataCollectionResponse response = workflowMetadataService.getAvailableWorkflows(availableWorkflowsRequest);

 // Get list of available workflow for the given content listing
 List<AvailableWorkflowMetadata> availableWorkflows = response.getWorkflows();

 // Can loop over list of AvailableWorkflowMetadata to find/show all available workflows


 // 2) Get Start step details to begin workflow
 WorkflowStartMetadataRequest startMetadataRequest = workflowMetadataService.newWorkflowStartMetadataRequestBuilder()
                                                                     .withWorkflowName(workflowName)
                                                                     .withRecords(objectName, records)
                                                                     .build();

 WorkflowStartMetadataResponse startMetadataResponse = workflowMetadataService.getWorkflowStartMetadata(startMetadataRequest);

 // List of control sections in the start step
 List<WorkflowStartStepMetadata> startStepMetadata = startMetadataResponse.getStartStepMetadataList();

 for (WorkflowStartStepMetadata metadata : startStepMetadata){
     WorkflowStartStepType metaDataType = metadata.getType();  // Type of Start control (Participant, date, etc.)

     List<WorkflowParameterMetadata> parameters = metadata.getParameters(); // Parameters needed to start the workflow

     for (WorkflowParameterMetadata param : parameters) {
         String paramName = param.getName();                           // used in input parameter key
         WorkflowInputValueType valueType = param.getDataType();       // used to set the value of the control
     }
 }

 // 3) Start workflow with these start inputs

 String participantName = "viewer__c";
 Long userId = 100l;
 Long groupId = 500l;
 List<String> userIds = VaultCollections.asList(userId.toString());
 List<String> groupIds = VaultCollections.asList(groupId.toString());

 String numberInput = "number__c";
 int number = 123;

 WorkflowInstanceService workflowInstanceService = ServiceLocator.locate(WorkflowInstanceService.class);

 // Set workflow participants input
 WorkflowParticipantInputParameter workflowParticipantInputParameter = workflowInstanceService.newWorkflowParticipantInputParameterBuilder()
             .withUserIds(userIds)
             .withGroupIds(groupIds)
             .build();

 // Create Start instance request with the builder
 WorkflowStartInstanceRequest startRequest = workflowInstanceService.newWorkflowStartRequestBuilder()
             .withWorkflowName(workflowName)
             .withRecords(objectName, records)
             .withInputParameters(numberInput, number)
             .withInputParameters(participantName, workflowParticipantInputParameter)
             .build();

 // Start workflow with start request and success and error handlers
 workflowInstanceService.startWorkflow(startRequest)
             .onSuccess(startResponse -> {
                 String workflowId = startResponse.getWorkflowId();
                 // Developer provided success handling logic here
             })
             .onError(startResponse -> {
                 // Developer provided failure handling logic here
                 if (startResponse.getErrorType() == ActionErrorType.INVALID_REQUEST) {
                     throw new RuntimeException(startResponse.getMessage());
                 } else {
                     // ...
                 }
             })
             .execute();  // needed to execute the action
 
 

Example: Retrieving and Executing Workflow Actions

The following code provides an example of retrieving available workflow actions that can be executed on a specified workflow and provides examples of executing WorkflowActions:
 
 {@literal @}RecordActionInfo(label="Record Action with WorkflowActions", object="product__v")
 public class RecordActionWithWorkflowActions implements RecordAction {

     {@literal @}Override
     public boolean isExecutable(RecordActionContext context) {
         String workflowId = "105";
         WorkflowInstanceService workflowInstanceService = ServiceLocator.locate(WorkflowInstanceService.class);
         List<WorkflowAction> workflowActions = getAvailableWorkflowActions(workflowInstanceService, workflowId);
         return !workflowActions.isEmpty();
     }

     {@literal @}Override
     public void execute(RecordActionContext context) {
         WorkflowInstanceService workflowInstanceService = ServiceLocator.locate(WorkflowInstanceService.class);
         String workflowId = "105";

         // provide logic to determine workflowAction
         WorkflowAction workflowAction = WorkflowAction.ADD_PARTICIPANTS;

         switch (workflowAction) {
             case ADD_PARTICIPANTS:
                 addParticipants(workflowInstanceService, workflowId);
                 break;
             case CANCEL_WORKFLOW:
                 cancelWorkflow(workflowInstanceService, workflowId);
                 break;
             case REMOVE_ITEMS:
                 removeItems(workflowInstanceService, workflowId);
                 break;
             case REPLACE_WORKFLOW_OWNER:
                 replaceWorkflowOwner(workflowInstanceService, workflowId);
                 break;
             case UPDATE_WORKFLOW_DUE_DATE:
                 updateWorkflowDueDate(workflowInstanceService, workflowId);
                 break;
             default:
                 break;
         }
     }

     private List<WorkflowAction> getAvailableWorkflowActions(WorkflowInstanceService workflowInstanceService, String workflowId) {
         // Retrieving all available workflow actions that can be executed on a specific workflow
         WorkflowInstanceRequest workflowInstanceRequest = workflowInstanceService.newWorkflowInstanceRequestBuilder()
             .withWorkflowId(workflowId).build();
         AvailableWorkflowInstanceActionsResponse workflowActionsResponse = workflowInstanceService.getAvailableWorkflowInstanceActions(workflowInstanceRequest);
         return workflowActionsResponse.getWorkflowActions();
     }

     private void addParticipants(WorkflowInstanceService workflowInstanceService,
                                  String workflowId) {
         String groupName1 = "part_approvers__c";
         List<String> newUsers1 = VaultCollections.asList("100001", "100002");
         List<String> newGroups1 = VaultCollections.asList("13500001");
         String groupName2 = "part_reviewers__c";
         List<String> newUsers2 = VaultCollections.asList("100003");

         WorkflowParticipantGroupInputParameter participantGroupParameter1 = workflowInstanceService.newWorkflowParticipantGroupInputParameterBuilder()
             .withParticipantGroupName(groupName1)
             .withUserIds(newUsers1)
             .withGroupIds(newGroups1).build();

         WorkflowParticipantGroupInputParameter participantGroupParameter2 = workflowInstanceService.newWorkflowParticipantGroupInputParameterBuilder()
             .withParticipantGroupName(groupName2)
             .withUserIds(newUsers2).build();

         WorkflowAddParticipantsRequest addRequest = workflowInstanceService.newWorkflowAddParticipantsRequestBuilder()
             .withWorkflowId(workflowId)
             .withInputParameters(VaultCollections.asList(participantGroupParameter1, participantGroupParameter2)).build();

         workflowInstanceService.addParticipants(addRequest)
             .onSuccess(addResponse -> {
                 String resultWorkflowId = addResponse.getWorkflowId();
                 // Developer provided success handling logic here
             })
             .onError(addResponse -> {
                 // Developer provided failure handling logic here
                 if (addResponse.getErrorType() == ActionErrorType.INVALID_REQUEST) {
                     throw new RuntimeException(addResponse.getMessage());
                 } else {
                     // ...
                 }
             })
             .execute(); // needed to execute the action
     }

     private void cancelWorkflow(WorkflowInstanceService workflowInstanceService, String workflowId) {
         WorkflowCancelRequest request = workflowInstanceService.newWorkflowCancelRequestBuilder()
             .withWorkflowId(workflowId)
             .withComment("This workflow was cancelled from ... for this reason...")
             .build();
         LogService logger = ServiceLocator.locate(LogService.class);
         workflowInstanceService.cancelWorkflow(request)
             .onSuccess(cancelResponse -> logger.info("Workflow [{}] successfully cancelled", workflowId))
             .onError(cancelResponse -> {
                 // Developer provided failure handling logic here
                 if (cancelResponse.getErrorType() == ActionErrorType.INVALID_REQUEST) {
                     throw new RuntimeException(cancelResponse.getMessage());
                 } else {
                     // ...
                 }
             }).execute();
     }

     private void removeItems(WorkflowInstanceService workflowInstanceService, String workflowId) {
         // e.g. get all workflow items and filter to desired items
         // perhaps by running vql to filter to approved verdicts completed by user1 on task1.
         WorkflowItemsResponse workflowItemsResponse = workflowInstanceService.getWorkflowItems(workflowId);
         List<WorkflowItem> workflowItems = workflowItemsResponse.getWorkflowItems();

         String objectName = null;
         List<String> recordIds = VaultCollections.newList();
         List<String> documentIds = VaultCollections.newList();
         for (WorkflowItem item: workflowItems.subList(0, 2)) {
             if (item.getWorkflowItemType() == WorkflowItemType.DOCUMENT) {
                 documentIds.add(item.getTypedWorkflowItem(WorkflowItemDocument.class).getId());
             } else {
                 WorkflowItemRecord itemRecord = item.getTypedWorkflowItem(WorkflowItemRecord.class);
                 objectName = itemRecord.getObjectName();
                 recordIds.add(itemRecord.getRecordId());
             }
         }

         WorkflowRemoveItemsRequest.Builder requestBuilder = workflowInstanceService.newWorkflowRemoveItemsRequestBuilder()
             .withWorkflowId(workflowId);
         if (objectName != null) {
             requestBuilder.withRecords(objectName, recordIds);
         } else {
             requestBuilder.withDocumentIds(documentIds);
         }

         workflowInstanceService.removeItems(requestBuilder.build())
             .onSuccess(removeResponse -> {
                 LogService logger = ServiceLocator.locate(LogService.class);
                 String resultWorkflowId = removeResponse.getWorkflowId();
                 logger.info("Successfully removed %s from workflow [%s]", removeResponse.getRemovedItems(), resultWorkflowId);
             })
             .onError(removeResponse -> {
                 ActionErrorType wfErrorType = removeResponse.getErrorType();
                 // Developer provided failure handling logic here
                 }
             )
             .execute();
     }

     private void replaceWorkflowOwner(WorkflowInstanceService workflowInstanceService, String workflowId) {
         WorkflowReplaceOwnerRequest request = workflowInstanceService.newWorkflowReplaceOwnerRequestBuilder()
             .withWorkflowId(workflowId)
             .withNewOwnerId("100001").build();
         workflowInstanceService.replaceWorkflowOwner(request)
             .onSuccess(replaceResponse -> {
                 String resultWorkflowId = replaceResponse.getWorkflowId();
                 // ...
             }).onError(replaceResponse -> {
                 ActionErrorType wfErrorType = replaceResponse.getErrorType();
                 // ...
             })
             .execute();
     }

     private void updateWorkflowDueDate(WorkflowInstanceService workflowInstanceService, String workflowId) {
         int year = 2023;
         int month = 12;
         int day = 31;
         ZonedDateTime newDueDate = ZonedDateTime.of(year, month, day, 0, 0, 0, 0, ZoneId.of("UTC"));
         WorkflowUpdateDueDateRequest request = workflowInstanceService.newWorkflowUpdateDueDateRequestBuilder()
             .withWorkflowId(workflowId)
             .withDueDate(newDueDate)
             .build();
         workflowInstanceService.updateWorkflowDueDate(request)
             .onSuccess(updateDueDateResponse -> {
                 String resultWorkflowId = updateDueDateResponse.getWorkflowId();
                 // ...
             }).onError(updateDueDateResponse -> {
                 ActionErrorType wfErrorType = updateDueDateResponse.getErrorType();
                 // ...
             })
             .execute();
     }
 }
 
 

Example: Completing a Job Step

The following example illustrates how to complete an active workflow job step specified by its job step ID. The job step ID is the unique identifier of a workflow job step instance (e.g. 1000241-15508). During execution of an SDK job started by a job step, the job step ID can be retrieved through WorkflowJobStepRequestExecutionContext.

 if (RequestContext.get().containsRequestExecutionContext(WorkflowJobStepRequestExecutionContext.class)) {
     String jobStepId = RequestContext.get().getRequestExecutionContext(WorkflowJobStepRequestExecutionContext.class).getWorkflowJobStepId();
     WorkflowInstanceService workflowInstanceService = ServiceLocator.locate(WorkflowInstanceService.class);
     WorkflowCompleteJobStepRequest request = workflowInstanceService.newWorkflowCompleteJobStepRequestBuilder()
         .withJobStepId(jobStepId)
         .withStatus("success__sys")
         .build();
     workflowInstanceService.completeJobStep(request)
         .onSuccess(response -> { ... })
         .onFailure(response -> { ... })
         .execute();
 }
 

Using WorkflowMetadataService

This service is used to retrieve workflow metadata. For example: requirements for starting a workflow (instructions, dates, field prompts), or available workflows to start on a collection of records or documents.

Example: Retrieving workflows available to be started on a collection of records

The following example shows how to retrieve workflows that can be started on a collection of records, based on security permissions and conditions.

 WorkflowMetadataService workflowMetadataService = ServiceLocator.locate(WorkflowMetadataService.class);

 String objectName = "object__c";
 List<String> recordIds = VaultCollections.asList("V6G000000001005", "V6G000000001006");
 WorkflowStartMetadataRequest request = workflowMetadataService.newWorkflowStartMetadataRequestBuilder()
     .withRecords(objectName, recordIds)
     .build();
 AvailableWorkflowMetadataCollectionResponse response = workflowMetadataService.getWorkflows();
 List<AvailableWorkflowMetadata> workflows = response.getWorkflows();
 

Using WorkflowTaskService

This service is used to retrieve information about and execute task actions. Examples of retrievable information: active tasks for a workflow instance, available actions on a task. Examples of task actions: updating a task's due date, reassigning a task, cancelling a task.

Example: Retrieving and Executing Task Actions

The following example shows how to retrieve executable actions for a task and execute them.

         // retrieve executable task actions for a task
         AvailableWorkflowTaskActionsRequest availableWorkflowTaskActionsRequest = workflowTaskService.newAvailableWorkflowTaskActionsRequestBuilder()
             .withTaskId(taskId)
             .build();
         List<WorkflowTaskAction> workflowTaskActions = workflowTaskService.getAvailableWorkflowTaskActions(availableWorkflowTaskActionsRequest)
             .getWorkflowTaskActions();
         for (WorkflowTaskAction workflowTaskAction: workflowTaskActions) {
             // based on the action type, execute the action
             switch (workflowTaskAction) {
                 case ASSIGN -> workflowTaskService.assign(
                     workflowTaskService.newWorkflowTaskAssignRequestBuilder()
                         .withTaskId(taskId)
                         .withAssigneeUserId("1000001")
                         .build()
                 )
                     .onSuccess(response -> { ... })
                     .onError(response -> { ... })
                     .execute();
                 case REASSIGN ->  workflowTaskService.reassign(
                         workflowTaskService.newWorkflowTaskReassignRequestBuilder()
                             .withTaskId(taskId)
                             .withAssigneeUserId("1000001")
                             .build()
                     )
                     .onSuccess(response -> { ... })
                     .onError(response -> { ... })
                     .execute();
                 case UNASSIGN -> workflowTaskService.unassign(
                         workflowTaskService.newWorkflowTaskUnassignRequestBuilder()
                             .withTaskId(taskId)
                             .build()
                     )
                     .onSuccess(response -> { ... })
                     .onError(response -> { ... })
                     .execute();
                 case CANCEL -> workflowTaskService.cancel(
                         workflowTaskService.newWorkflowTaskCancelRequestBuilder()
                             .withTaskId(taskId)
                             .build()
                     )
                     .onSuccess(response -> { ... })
                     .onError(response -> { ... })
                     .execute();
                 case UPDATE_DUE_DATE -> workflowTaskService.updateDueDate(
                         workflowTaskService.newWorkflowTaskUpdateDueDateRequestBuilder()
                             .withTaskId(taskId)
                             .withDueDate(ZonedDateTime.now())
                             .build()
                     )
                     .onSuccess(response -> { ... })
                     .onError(response -> { ... })
                     .execute();
             }
         }