Search

Saturday, 18 July 2015

Structuring Salesforce Invocable Methods

Invocable Methods are an important addition to the platform and Ive been calling for a complete overhaul of the Salesforce workflow engine for a long time and finally Process Builder was introduced a couple of releases back. 

There a few issues and limitations of Invocable Methods however:

  1. Passing Sobject lists appears not to work and instead you have to pass Ids of the Sobjects and then perform a SOQL to get the Sobjects, so you have to be mindful of SOQL limits. I would expect Salesforce to fix this issue in future releases, so this might go away.


  1. Another limitation is that you can only have 1 Invocable Method per class, which means you can end up having many classes. There is a neat way to get around this however:

Lets consider 2 examples. One Invocable Method sends an email introducers customers to The Self Evolving Software app, the 2nd Invocable Method updates a field on the Account to make post codes correctly formatted. 


@InvocableMethod(label='Setup_Salesforce_To_Salesforce_Email' description='Sends a Email To Explain Setup Of Salesforce To Salesforce')
public static void sendBenefitsEmail(ID[] emls){
      Attachment[] att = [Select id,Body, Name From Attachment
      where name='SES Introduction.pdf'];
       
      UtilEmail.sendEmail(emls,'How To Use The Self Evolving Software App', att);        
}




 @InvocableMethod(label='Format postcode on Account' description='Format postcode on Account')
public static void formatPostcode(ID[] accs){
      Account[] acc = [Select BillingPostalCode From Account
      where Id In :accs];
      for (Account eachacc : acc){
            eachacc.BillingPostalCode =
            UtilFormats.postcodeFormatting(eachacc.BillingPostalCode);
      }

      update acc;
}








The issue here is that we would have to create 2 classes with 1 Invocable Method in each.

The solution is to combine all Invocable Methods into an InvocableMethodHandler class and call to separate classes where the actions will take place




We first need to create a wrapper class to hold our data

In the labels for each InvocableVariable you probably want to display something a bit shorter as this will appear in the process builder.

 public with sharing class KeyValueInv {
      @InvocableVariable(label='Optional key if you want to represent a collection' required= false)
      public String key;
      @InvocableVariable(label='Stores the value' required= true)
      public String value;
      @InvocableVariable(label='The data type of the value' required=true)
      public String fieldtype;
      @InvocableVariable(label='This identifies the function to call' required=true)
      public String type;
     
      public KeyValueInv(String thiskey, String thisvalue, String thisfieldtype, String thistype){
            this.key = thiskey;
            this.value = thisvalue;
            this.fieldtype = thisfieldtype;
            this.type = thistype.toUpperCase();
      }


}

Below is the only invocable class and method you will ever need to create as we can send to it any type of data to the KeyValueInv class, plus in the InvocableMethodHandler we identify the function to call

public with sharing class InvocableMethodHandler {
      @InvocableMethod(label='' description='')
      public static void processType(KeyValueInv[] kvLst){
            if (kvLst[0].type == 'Send Benefits Email'){
                  UtilClass.sendBenefitsEmail(kvLst);
            }
            else if (kvLst[0].type == 'Format Postcode'){
                  UtilClass.formatPostcode(kvLst);
            }
           
      }

}



 public static void sendBenefitsEmail(kvLst[] kvs){
    //code .....
 }


public static void formatPostcode(kvLst[] kvs){
    //code .....
}





Now when you create your process builder you will be able to set the 'Send Benefits Email' as or 'Format Postcode' and this will decide which function to ultimately to call.

No comments:

Post a Comment

Note: only a member of this blog may post a comment.