Skip to main content

How to Call Invocable Actions from Apex

How to Call Invocable Actions from Apex in Salesforce?

Call Invocable Actions from Apex

In Salesforce Winter 23' release we can now use Invocable Actions in Apex Class.

In this blog we will see how we can make use of new Invocable.Action Apex Class in order to use custom or standard Invocable Actions via apex.

What are Invocable Actions ?
The invocable actions mechanism allows to create custom code and package it into components/actions available in declarative tools, such as flow. It is a simple idea to provide input values that the apex manipulations and transactions and then finally gives the desired output values.

New Invocable.Action class has following methods -

We will take two examples to use the above methods, 1 for each custom Invocable Action and standard Invocable actions.

Call Standard Invocable Actions from Apex

Let us take chatterPost as an example for Standard Invocable Actions.

Step 1: Check the type and other input parameters that are needed for chatterPost.
Login into Workbench => Utilities => REST Explorer => GET Request

/services/data/v54.0/actions/standard/chatterPost


If we expand the input folder we can see the input parameters that are needed. Similarly for expected output we can see that in Output folder.

Here ,

Input Parameters are :-

  1. text -String
  2. subjectNameOrId - String
  3. type
  4. communityId
  5. visibility
Output parameters:-
  1. feedItemId
Step 2: Create an Apex Class and a method.
for example -
ClassName - TestInvocableActionViaApexW23
MethodName - postToChatter
For chatterPost only text and subjectNameOrId are required parameters and rest are optional.

So lets give following values;-
text - 'This is an example Chatter post.'
subjectNameOrId - recordId (Any recordId where you want to post a Chatter feed)

TestInvocableActionW23.cls
public class TestInvocableActionW23 {
    public static void postToChatter(String recordId) {
        //set standard action as 'chatterPost'
         Invocable.Action action = Invocable.Action.createStandardAction('chatterPost');
         // set text value as string type
         action.setInvocationParameter('text', 'This is an example Chatter post.');
         // set the record Id value
         action.setInvocationParameter('subjectNameOrId', recordId);
         //invoke the Invocation.Action
         List<Invocable.Action.Result> results = action.invoke();
         System.debug('result : ' + results); //print result
         if (results.size() > 0 && results[0].isSuccess()) {
             System.debug('Created feed item with ID: ' +
             results[0].getOutputParameters().get('feedItemId'));// Debug newly created FeedIemId
        }        
    }
}

Step 3 : From anonymous window run
TestInvocableActionViaApexW23.postToChatter('0016F00002V58eaQAB')
We will get the following result from which we can extract the newly created feedItemId which is the output parameter.

(Result:[action=Action:[invocations=({subjectNameOrId=0016F00002V58eaQAB, text=This is an example Chatter post.}), name=null, namespace=null, type=chatterPost], errors=(), invocationParameters=(already output), outputParameters={feedItemId=0D56F0000EL2yHfSQJ}, success=true])

Step 4: Verify.

Call Custom Invocable Actions from Apex
Step 1
: Check the existing actions in your org
Login into Workbench => Utilities => REST Explorer => GET Request
/services/data/v54.0/actions/custom


Step 2: Click on apex actions and pick /check the details of the existing action you want to use or you can create a new Invocable method.


Here we will use existing Apex class ChangeOwnerFromflow with Invocable methods .

In this class ChangeOwnerFromflow we have

Input Parameters are :-

  1. recIds - List<String>
  2. user_name - String
Output parameters:-
  1. N/A (here it is N/A, but we can create one as per requirement.)



Step 3: ChangeOwnerFromflow.cls

public class ChangeOwnerFromFlow {      
    public class FlowInputs {        
        @InvocableVariable public List<String> recIds;        
        @InvocableVariable public String user_Name;    
    }
    @InvocableMethod    
    public static void updateOpp (List<FlowInputs> requests) {
        // get all Ids
        List<Id> newIds = new List<Id>();
        String username;
        for (FlowInputs request : requests) {
            newIds.addAll(request.recIds);
            username = request.user_Name;          
        }
        String str = '%'+username+'%';
        User usernameId = [Select id from User where Name Like :str limit 1];
        // Get the sObject token from the first ID (the List contains IDs of sObjects of the same type).
        Schema.SObjectType token = newIds[0].getSObjectType();
        // Using the token, do a describe and construct a query dynamically.
        Schema.DescribeSObjectResult dr = token.getDescribe();
        String queryString = 'SELECT id,ownerId FROM ' + dr.getName() +  ' WHERE ';
        for(ID objId : newIds) {
            queryString += 'Id=\'' + objId + '\' OR ';
        }    
        // Remove the last ' OR'
        queryString = queryString.subString(0, queryString.length() - 4);
        sObject[] objDBList = Database.query(queryString);
        System.assert(objDBList.size() > 0);        
        // Update the owner ID on the sObjects
        for(Integer i=0;i<objDBList.size();i++) {
            objDBList[i].put('ownerId', usernameId.id);
        }            
        Database.SaveResult[] srList = Database.update(objDBList, false);
        for(Database.SaveResult sr : srList) {
            if (sr.isSuccess()) {
                System.debug('Updated owner ID successfully for ' + dr.getName() + ' ID ' + sr.getId());
            }
            else {
                System.debug('Updating ' + dr.getName() + ' returned the following errors.');
                for(Database.Error e : sr.getErrors()) {
                    System.debug(e.getMessage());
                }
            }
        }
    }
}

Step 4 : Write the Apex Class to use Invocable action class.
for example -

ClassName - TestInvocableActionViaApexW23
MethodName - changeOwnerName


For ChangeOwnerFromFlow both recIds and user_name are required parameters.

TestInvocableActionW23.cls
public class TestInvocableActionW23 {
    public static void changeOwnerName() {
        List<Opportunity> oppList = new List<Opportunity>();
        oppList = [Select Id from Opportunity Limit 10];
        List<String> recIDs = new List<String>();
        for(Opportunity opp : oppList){
            recIDs.add(opp.Id);
        }
        //set standard action type as 'apex' and name as 'ChangeOwnerFromFlow'
        Invocable.Action action = Invocable.Action.createCustomAction('apex', 'ChangeOwnerFromFlow');
        // set List<String> recdIds
        action.setInvocationParameter('recIds', recIDs);
        //set user_name
        action.setInvocationParameter('user_Name','Amit Agarwal');
        List<Invocable.Action.Result> results = action.invoke(); //invoke the Invocation.Action
        System.debug('result : ' + results); // print result
    }
}

Step 5 : From anonymous window run
TestInvocableActionViaApexW23.changeOwnerName();

We will get the following result.
Result:-
(Result:[action=Action:[invocations=({recIds=(0066F000016jkrhQAA, 0066F000016jkveQAA, 0066F000016jkvyQAA, 0066F000016jkwNQAQ, 0066F000016jl21QAA, 0066F000016jl2BQAQ, 0066F00000vVBE6QAO, 0066F00000vVBEDQA4, 0066F00000vVBEEQA4, 0066F00000vVBESQA4), user_Name=Amit Agarwal}), name=ChangeOwnerFromFlow, namespace=null, type=apex], errors=(), invocationParameters=(already output), outputParameters=null, success=true])


References:-

Salesforce Winter 23' release notes
Invocable Actions

Thank you all !
#Keep learning #Keep Sharing :)

Recent blogs:

Enhanced Lightning DataTable
Custom Toast Message in LWC
Generic Modal Box in LWC


Comments

Popular posts from this blog

How to create custom polymorphic field using LWC ?

How to create custom polymorphic field using LWC ? In this blog we will see how we can make polymorphic lookup field using LWC. What is Polymorphic field? A polymorphic field is one where related object might be one of the several different types of objects. There can be a use case where a customer wants to connect one object with multiple objects- i.e, relationships between objects or relate a child object to multiple parents's ojects. For example, in task Object we have three such polymorphic fields. The WhoId(Name) relationship of Task can be with Contact or a Lead. Assigned To field can be a User or a Queue. Similarly, a WhatId(Related To) relationship field of Task can be with many other objects like Accounts, Opportunities etc. In Salesforce, currently we do not have any OOTB option or may be we can say we do not have a datatype for polymorphic field which we can create but if required we can create a custom component to facilitate the same functionality. So let's get

How to update Field Level Security in bulk ?

Assign Field Level Security(FLS) in Salesforce Demo:- In this blog we will see the easy way to update Field Level Security(FLS) for Permission sets/Profiles in bulk. I have created a tool to make the Admins job a little easier. Before jumping to tool let us see the different standard approach we follow to update FLS in Salesforce.                     As an admin we usually update FLS from salesforce setup/UI. If we are working on a new Application with many Permission sets and Objects with 100+ fields it can be very time consuming task. Using this tool we can assign FLS in just few mins. Let us take an example. Suppose we have a new application and we have created 20 Permission sets and 8 Profiles . Now there are 10 Objects in all and in each object we have 15 fields for which we need to update FLS for above Permission sets and Profiles. Let us first see the different approach to assign FLS in Salesforce. We have two ways in which we can update FLS for a particular field.  1 .To upd

How to use Hyperlink in Custom Toast Notification message using LWC

  Use Hyperlink in Custom Toast Notification message using LWC   We all know that a component can send a toast notification that pops up to alert users of a success, error, or warning. A toast can also simply provide information to the user. But what if we need a hyperlink on the message to navigate to the records on the message body. Yes, we can put Links as well on the message body as we can see in Standard Notification Toasts. This is very simple just we need to remember few things. We should know how to use Navigation Services by using NavigationMixin.GenerateUrl method. Let us see the functionality in this blog. To display a toast notification in Lightning Experience or Experience Builder sites we import ShowToastEvent from the lightning/platformShowToastEvent module. We use this ShowToastEvent to provide feedback to a user following an action, such as after a record is created. Now in this blog we will see how to add hyperlink in the message of the Show Toast event and navig