How to Call Invocable Method from Salesforce Flow?
Invocable Method provides a very powerful way to use Apex functions not available out of the box in Salesforce Flow.
1. What are Invocable Actions?
Invocable actions give developers an opportunity to write any complex logic in Apex and expose it into Flow Builder.
2. What is an Invocable Method?
In order to call an Apex method from Flow you will have to annotate that method with @InvocableMethod.
This code sample shows an invocable method with the generic sObject data type.
public with sharing class GetFirstFromCollection {
@InvocableMethod
public static List <Results> execute (List<Requests> requestList) {
List<SObject> inputCollection = requestList[0].inputCollection;
SObject outputMember = inputCollection[0];
//Create a Results object to hold the return values
Results response = new Results();
//Add the return values to the Results object
response.outputMember = outputMember;
//Wrap the Results object in a List container
//(an extra step added to allow this interface to also support bulkification)
List<Results> responseWrapper= new List<Results>();
responseWrapper.add(response);
return responseWrapper;
}
}
public class Requests {
@InvocableVariable(label='Records for Input' description='yourDescription' required=true)
public List<SObject> inputCollection;
}
public class Results {
@InvocableVariable(label='Records for Output' description='yourDescription' required=true)
public SObject outputMember;
}
}
3. InvocableMethod Considerations
- The invocable method must be static and public or global, and its class must be an outer class.
- Only one method in a class can have the InvocableMethod annotation.
- Other annotations can’t be used with the InvocableMethod annotation.
- There can be at most one input parameter and its data type must be one of the following:
- A list of a primitive data type or a list of lists of a primitive data type – the generic Object type is not supported.
- A list of an sObject type or a list of lists of an sObject type.
- A list of the generic sObject type (List<sObject>) or a list of lists of the generic sObject type (List<List<sObject>>).
- A list of a user-defined type, containing variables of the supported types or user-defined Apex types, with the InvocableVariable annotation.
- If the return type is not Null, the data type returned by the method must be one of the following:
- A list of a primitive data type or a list of lists of a primitive data type – the generic Object type is not supported.
- A list of an sObject type or a list of lists of an sObject type.
- A list of the generic sObject type (List<sObject>) or a list of lists of the generic sObject type (List<List<sObject>>).
- A list of a user-defined type, containing variables of the supported types or user-defined Apex types, with the InvocableVariable annotation.
4. Invocable Method to Approve, Reject & Recall Records in an Approval Process Using Salesforce Flow
This code sample shows an Invocable Method to Approve, Reject & Recall records in an Approval Process
public without sharing class DYDCApprovalProcess {
@InvocableMethod(label='Approval Process Action' description='Invocable Method to Process Approval Requests')
public static List<Results> processApprovalRequestAction(List<Requests> requests) {
List<Results> responseWrapper = new List<Results>();
Map<Id, Id> processInstanceWorkItemMap = getProcessInstanceIdfromRecordId(requests);
for (Requests curRequest : requests) {
Results response = new Results();
Approval.ProcessWorkitemRequest approvalWorkItem = new Approval.ProcessWorkitemRequest();
approvalWorkItem.setComments(curRequest.comments);
approvalWorkItem.setAction(curRequest.action);
if(curRequest.approvalRecordId != null && processInstanceWorkItemMap.get(curRequest.approvalRecordId) != null)
{
approvalWorkItem.setWorkitemId(processInstanceWorkItemMap.get(curRequest.approvalRecordId));
}
// Submit the request for approval
Approval.ProcessResult approvalResult = Approval.process(approvalWorkItem);
response.isSuccess = approvalResult.isSuccess();
Database.Error[] errors = approvalResult.getErrors();
response.errorString = getErrorInfo(errors);
response.currentApprovalProcessStatus = approvalResult.getInstanceStatus();
//Wrap the Results object in a List container
responseWrapper.add(response);
}
return responseWrapper;
}
public static String getErrorInfo(Database.Error[] errors) {
String errorStrings = '';
if (errors != null) {
for(Database.Error error : errors) {
errorStrings = errorStrings + ' ' + error.getMessage();
}
}
return errorStrings;
}
public static Map<Id,Id> getProcessInstanceIdfromRecordId (List<Requests> requests){
Set<Id> recordSet = new Set<Id>();
Set<Id> processInstanceIdSet = new Set<Id>();
Map<Id, Id> processInstanceMap = new Map<Id,Id>();
Map<Id, Id> processInstanceWorkItemMap = new Map<Id,Id>();
for (Requests curRequest : requests) {
recordSet.add(curRequest.approvalRecordId);
}
for (ProcessInstanceWorkitem invsWorkItem : [select Id, ProcessInstance.TargetObjectId from ProcessInstanceWorkitem
where ProcessInstance.TargetObjectId in : recordSet])
{
processInstanceWorkItemMap.put(invsWorkItem.ProcessInstance.TargetObjectId, invsWorkItem.Id);
}
return processInstanceWorkItemMap;
}
public class InvocableErrorException extends Exception {
}
public class Requests {
@InvocableVariable
public String approvalRecordId;
@InvocableVariable
public String comments;
@InvocableVariable
public String action; // 'Approve', 'Reject'. 'Removed'
@InvocableVariable
public List<String> nextApproverIds;
}
public class Results {
@InvocableVariable
public Boolean isSuccess;
@InvocableVariable
public String errorString;
@InvocableVariable
public String currentApprovalProcessStatus; //Approved, Rejected, Removed or Pending.
}
}
The above Invocable Method will be available as a Flow Action.
You can create a screen flow to use this action.
You can use the flow as a Quick Action to be called on click of a Button.
5. Additional Resources
Recommend Articles
- How to resolve ‘Apex CPU time limit exceeded’ error in Salesforce
- Salesforce Inspector Chrome Extension Explained
- How to Resolve ‘System.LimitException: Too Many SOQL Queries: 101’ Error?
- Top 7 VSCode (Visual Studio Code) Extensions for Salesforce Developers
- Salesforce Flow Best Practices & Standards Checklist Summer 22