Salesforce Integration Tips & Tricks

Hi I’ve been working with apex coding a bit lately and I’ve tried to integrate Salesforce with external systems using rest API.

My use case was the following :  when creating a contact I wanted to call the external API , try to find some contact related info there, update the contact itself with the external Key and some other info coming from the external system.

This seems an easy task but it is not so easy as it seems ….

In order to perform a change on a record that you are creating/updating , Salesforce offers the trigger functionality,

however you cannot perform an http request inside a trigger (Salesforce rightly says that external calls cannot respond in a quick and predictable way so they cannot stay in a trigger call).

@future directive comes to rescue because simply marking the synchronous method with this directive makes him asynchronous and executed actually outside from the trigger context.

This however brings another interesting challenge: if we execute our call outside the trigger scope how we are supposed to change the records that are currently updated ?

This can be solved passing to the asynchronous methods the Ids of the records being changed and applying the change to them outside the trigger context.

But now we have the “final boss” to be beaten 🙂

This is what happens if we put in place the ideas that we described:

  1. User or Process changes a record
  2. This makes the trigger react
  3. The async call is made
  4. In the async call , since we are outside the trigger context we call the update command to change the records
  5. the trigger reacts again
  6. infinite loop

Salesforce platform is so smart to detect the infinite loop and stop you, but it is clear that we have to fix this.

The trick here is to detect who is making the trigger react, if the trigger is activated by a user/process we should call the async method, if the trigger is activated by an aync method we do nothing so we interrupt the infinite loop.

Here some sample code that shows how is done the trigger:

trigger ExternalIDTrg on Contact (after insert, after update) {
   // Contact[] contacts = Trigger.new;
   String tempUID=null;
    System.debug('Trigger Started:');
    for ( Contact a : trigger.new ){
      if (!System.isFuture() && !System.isBatch())
          {
            ExternalIDConnector.UpdateContact(a.Id);
            System.debug('Future Call Done');
          }
    }
}

As you can see we detect with System.isFuture() if the call is coming from a future method. We call a method that matches a Contact using the email in the external system and if we find it we write the Id in the externalId field of Salesforce.

 

 @future(callout=true)
    public static void UpdateContact(ID ContactId)
    {
      String tempUID=null;
      for ( Contact a : [
        Select Id, Email, ExternalID__c
        from Contact
        where Id = :ContactId
        ])
        {
          if ( a.ExternalID__c == null && a.Email !=null){
                   System.debug('Contact Email: '+a.Email);
                  tempUID=ExternalIDConnector.ExternalIDFromEmail(a.Email);
                  System.debug('tempUID: '+tempUID);
                    if (tempUID!=null)
                    {
                        a.ExternalID=tempUID;
                        System.debug('ExternalID: '+a.ExternalID__c);
                        update a;
                    }
              }
        }
    }
 

Notice the @future(callout=true) directive that allows us to call an http request inside the method.