Table of Contents
Concept
Let’s consider a scenario, we want to callout to an external service to post or get some data when we create or update a record and we do want to show a toast message response based on that callout.
Now, as we are aware callouts cannot be made from triggers synchronously as that would hold up the database transaction until the callout is completed. Considering the governor limits in place we can have up to 120 seconds. This in turn could cause significant contention with other transactions and might impact performance.
The only way that you can execute a http callout from a trigger is to run asynchronously. For example by executing a method with the @future method in a separate thread so as to not stall the transaction awaiting a response from the callout.
HTTP Callout Example to external web services
Taking an instance of a lead record that needs to update a geotag via a webservice. We can start as below.
Have a trigger to run the context we require. We must keep the trigger logic less, but have put it here for the sake of not having three classes here.
trigger triggerLead on Lead (after insert, after update) {
if(System.isFuture()) {
return; // This is a recursive update, let's skip
}
Set<Id> updateLead = new Set<Id>();
for(Integer i = 0, s = Trigger.new.size(); i < s; i++) {
Lead oldRecord = Trigger.isInsert? null: Trigger.old[i], newRec = Trigger.new[i];
if((Trigger.isInsert && newRec.geoTag__c != null) ||
(Trigger.isUpdate && newRec.geoTag__c != null &&
(newRec.Region_Code__c == null || newRec.geoTag__c != oldRecord.geoTag__c))) {
updateLead.add(newRec.Id);
if(updateLead.size() == 100) { // Max callout limit 100
GetGeoTag.fetchGeoTag(updateLead);
updateLead.clear();
}
}
}
if(updateLead.size() > 0) {
GetGeoTag.fetchGeoTag(updateLead);
}
}
We can use a future call to then make a callout and update the record on that field.
public with sharing class GetGeoTag {
@future (callout=true)
static public void fetchGeoTag(Set<Id> leadIDs){
Lead[] records = [Select id, geoTag__c from Lead where id = :leadIds];
for(Lead record: records) {
HttpRequest req = new HttpRequest();
req.setEndpoint('https://api.geotag.com/'+record.geoTag__c+'?access_key=e767bdd2ee983a9407fccd6ccb7bff0e');
req.setMethod('GET');
HttpResponse res = new http().send(req);
Map<string,object> m = (Map<string,object>)JSON.deserializeUntyped(res.getbody());
String regioncode=(String)m.get('region_code');
String regionname=(String)m.get('region_name');
String countrycode=(String)m.get('country_code');
String countryname=(String)m.get('country_name');
record.Region_Code__c = regioncode;
}
update records;
}
}
If you are trying to return a response to the user, create a process builder which runs when record is update. Using that we can show a toast message. What else can we do ? Have opinions on that ? Feel free to drop comment
Read More: Salesforce Integration Interview Questions