In this blog post, we are going to see how we can do callouts
from apex trigger.
As we know that trigger runs synchronously we cannot make a callout to external system
from trigger, this is because a trigger cannot wait for the execution to complete
as this can cause performance issue, however an apex trigger can invoke a
callout when the callout is made from a method which is defined as
asynchronous.
Below is the sample structure to call Apex class method from trigger which makes callouts.
APEX TRIGGER:
trigger checkMeaningTrigger on checkMeaning__c (after
insert) {
if(avoidRecursionClass.booleanvar){
avoidRecursionClass.booleanvar=false;
// Avoid recursion.
populateMeaning.findMeaning(trigger.newmap.keyset());
// Passing ids of records.
}
}
APEX CLASS:
public class populateMeaning {
// Callout from trigger should be asynchronous
@future(Callout=True)
// Future method is always static
// Getting the ids of the account
public static void
findMeaning(Set<id> IdSet){
// CALLOUT CODE
}
}
SCENARIO:
We are having the requirement that whenever a contact record is inserted in “Salesforce ORG1” we have
to write a trigger on “After Insert” event on contact record which will call
the apex class method and the method will do callout to other Salesforce org i.e
(“Salesforce ORG2”) webservice. This webservice will insert the contact record
in “Salesforce ORG2” with the information receives from “Salesforce ORG1”.
REMOTE SITE Setting IN “Salesforce ORG1”.
Now the question is what is connected
app?
For external
application that needs to authenticate with Salesforce we need to create a
connected app so as to inform Salesforce about the new authentication entry
point. Connected app use standard OAuth 2.0 protocol to authenticate.
Note down
the Consumer key, Consumer secret
(We have to provide this information to “Salesforce ORG1” for authentication purpose along with username, password, security token of
user which “Salesforce ORG1” will be
using for authentication).
Now let’s create
a trigger in “SALESFORCE ORG1” as shown below.
APEX
TRIGGER:
trigger maintrigger on Contact (after insert) {
Set<id> conIdSet=new Set<id>();
for(Contact con:trigger.new){
if(con.email!=Null){
conIdSet.add(con.id);
}
}
if(conIdSet.size() > 0){
callWebserviceClass.getConList(conIdSet); // Calling apex class method
}
}
Now let’s
create a apex class “callWebserviceClass” in “SALESFORCE ORG1”.
APEX
CLASS:
public class callWebserviceClass {
private string cKey =’XXXXXXXXXXXXXXXXXXXXXX’;
private string cSecret = ' XXXXXXXXXXXXXXXXXXXXXX
';
private string uName = ‘XXXXXXXXXXXXXXXXXXXXXX’;
private string passwd = ‘PASSWORD+SECURITYTOKEN’;
public class responseWrapper {
public string id;
public string access_token;
public string instance_url;
}
public string getRequestToken() {
string reqBody =
'grant_type=password&client_id=' + cKey + '&client_secret=' + cSecret +
'&username=' + uName + '&password=' + passwd;
Http h = new Http();
HttpRequest req = new HttpRequest();
req.setBody(reqBody);
req.setMethod('POST');
req.setEndpoint('https://login.salesforce.com/services/oauth2/token');
HttpResponse hresp = h.send(req);
responseWrapper wResp =
(responseWrapper) JSON.deserialize(hresp.getBody(), responseWrapper.class);
system.debug('Instance url' +
wResp.instance_url);
system.debug('session id' + wResp.access_token);
return wResp.access_token;
}
@future(callout = true)
public static void getConList(Set < id
> conIdSet) {
String accToken;
string responseBody;
string endPoint =
'https://ap5.salesforce.com/services/apexrest/createContactRecord';
callWebserviceClass obj = new
callWebserviceClass();
accToken = obj.getRequestToken();
system.debug('access token' +
accToken);
if (accToken != '') {
for (Contact con: [SELECT id,
firstName, lastName, email from contact where id in: conIdSet]) {
system.debug('JSON' +
JSON.serialize(con));
Http h1 = new Http();
HttpRequest req1 = new
HttpRequest();
req1.setHeader('Authorization',
'Bearer ' + accToken);
req1.setHeader('Content-Type',
'application/json');
req1.setMethod('POST');
req1.setBody(JSON.serialize(con));
req1.setEndpoint(endPoint);
HttpResponse hresp1 =
h1.send(req1);
system.debug('hresp1' +
hresp1);
}
}
}
}
Now create a WEBSERVICE
in “SALESFORCE ORG2” as below.
@RestResource(urlMapping='/createContactRecord/*')
global with sharing class
createContactRecordCLass {
@HttpPost
global Static string fetchAccount(){
RestRequest req = RestContext.request;
RestResponse res = Restcontext.response;
string
jsonString=req.requestBody.tostring();
responseWrapper wResp=(responseWrapper)
JSON.deserialize(jsonString,responseWrapper.class);
Contact obj=new Contact();
obj.firstName=wResp.FirstName;
obj.lastName=wResp.LastName;
obj.email=wResp.email;
Insert obj;
return 'Success';
}
global class responseWrapper{
global string FirstName;
global string LastName;
global string email;
}
}
Now let’s try
to upload a .csv file containing 2 contact records in “SALESFORCE
ORG1” as shown in the below image.
Now let’s see
the result from “SALESFORCE ORG2” we have two contacts created in ORG2 as well.
Nice article, very well explained
ReplyDeletethank you, but custom fields are not getting populated in destination org
ReplyDeleteHey I am facing the same issue. did you figure out how to do this?
DeleteThis simple article has cleared lot of Concepts. Thanks
ReplyDeleteThank You.
ReplyDeleteVery Nice Explained
ReplyDelete