RSS feed for blog Linkin Skype Mail Me Twitter

Stickfight

Blog Category: saleforce

Salesforce: Same Code Different Triggers

In Salesforce the same bit of code can be triggered a lot of different ways and with calls to third parties there are different rules for the different ways of calling stuff.

For example take this bit of code, in it we are just passing a contact ID and it is going to go and talk to a third party web service, inside the “setUpRequest” it’s going to update the third party with the details of the Salesforce Contact and in return recive some bits and bobs from the third party to update the Saleforce side. Basic syncing between two parties

public class BlogFramework {

    public Static Void UpdateContactFromExternalWebService(String contactID) {
                Http h = new Http();
                HttpRequest request = setUpRequest(contactID);
                HttpResponse response = h.send(request);
    }           

}


we want this thing to happen at two different times:

  1. When a user manually updates a contact and then just saves it: we want the sync to happen instantly so the user can see immediately what’s happened and what’s been updated.
  2. On schedule: The content might not be updated in Salesforce at all, all changes might happen in the third party but the details still have to be kept up to date for reports and views etc.

So this bit of code has to be callable both from a Schedule and from a save Trigger

let’s take the save trigger first, as it is now it won’t work, you will get the error “Callout from triggers are currently not supported.” error if you try, normally you would just pop the annotation “@Future(callout=true)”1 at the top of this function and that would solve that but as you will see later on we can’t do that so what we’re going to do is have a little wrapper function that has the @future annotation and from that it’s going to call are real function.

@Future(callout=true)
public Static Void UpdateContactFromExternalWebServiceTrigger(String contactID) {
        BlogFramework.UpdateContactFromExternalWebService(contactID);
}   


we can then put that wrapper functions in our contact save trigger and everything will work perfectly

trigger ContactTriggerAllEvents on Contact (
    before insert,
    before update,
    //before delete,
    after insert,
    after update
    //after delete,
    //after undelete
    ) 
    {
        for(Contact cnt:Trigger.new)
        {
            BlogFramework.UpdateContactFromExternalWebServiceTrigger(cnt.ID); 
        }        
    }


Next comes calling it from a schedule, if we had put the @future annotation on the actual function this would fail because you cannot call a future function from a scheduled action but we dont have that issue now, what you DO have to do is bolt-on the “Database.AllowsCallouts” to your batch object as seen below

global class UpdateFromAzpiral implements Database.Batchable<sObject>, Database.AllowsCallouts{

    // Get all the contacts
    global Database.QueryLocator start(Database.BatchableContext BC){
        return Database.getQueryLocator([SELECT Id FROM Contact]);
    }

    // The executeBatch method is called for each chunk of objects returned from the start function.
    global void execute(Database.BatchableContext BC, List<Contact> scope){
      for(Contact c : scope){
         BlogFramework.UpdateContactFromExternalWebService(c.ID);
      } 
    }

    //The finish method is called at the end of a sharing recalculation.
    global void finish(Database.BatchableContext BC){
    }

}


Now your batch object will be allowed to do callouts.

Putting all these bits together means you can have a single function that calls out to third parties that can be triggered from either a Schedule or an ordinary Trigger.


  1. The “@Future(callout=true)” annotation basically means that the salesforce code does not stop and wait before doing other things this means that calls to third parties does not slow down the salesforce UI. 

Latest Blogs