Yes it possible to do callouts from batch apex in Salesforce.
To make callouts from batch apex ensure that your Batch Apex class implements
the Database.AllowsCallouts interface. This interface allows the batch job to
make callouts.
global class
YourBatchClass implements Database.Batchable<SObject>, Database.AllowsCallouts
{
// Batch Apex logic here
}
In this tutorial, we will guide you through the process of
making callouts from Batch Apex in Salesforce. We will focus on scenario where
the external system is also Salesforce, demonstrating how to leverage the power
of Batch Apex to streamline communication between Salesforce environments.
In this batch class, our mission is to efficiently fetch all
contacts where the custom field 'SFDCID__c' is not null. Once identified, we'll
seamlessly transmit this curated set of contacts to an external Salesforce
system.
Note: Start, execute,
and finish methods can implement up to 100 callouts each.
Batch Class
Created in ORG A:
In the start method of batch class , we are doing a callout
to ORG B token URL to get the access token and then this access token will be
used in execute method to send the POST call to ORG B for contact creation.
global class
BatchApexCalloutClass implements Database.Batchable < sObject > , Database.AllowsCallouts, Database.Stateful {
public String query = 'Select
ID,FirstName,LastName,Email,SFDCID__c from Contact Where SFDCID__c!= null';
global String accToken;
global String instanceurl;
public class responseWrapper {
public string id;
public string access_token;
public string instance_url;
}
List < Contact > updatedConList = new
List < Contact > ();
global Database.QueryLocator
start(Database.BatchableContext BC) {
String endpointthirdpartysystem =
'https: //farukh-dev-ed.my.salesforce.com/services/oauth2/token';
String cKey;
String cSecret;
List < Store_Cred__mdt >
connectionParam = [SELECT Id, MasterLabel, client_id__c, client_secret__c,
username__c, password__c from Store_Cred__mdt];
if (connectionParam.size() > 0) {
cKey =
connectionParam[0].client_id__c;
cSecret =
connectionParam[0].client_secret__c;
}
System.debug('Store_Cred__mdt' +
connectionParam);
string reqBody = 'grant_type=client_credentials&client_id='
+ cKey + '&client_secret=' + cSecret;
Http h = new Http();
HttpRequest req = new HttpRequest();
req.setBody(reqBody);
req.setMethod('POST');
req.setEndpoint('https://farukh-dev-ed.my.salesforce.com/services/oauth2/token');
HttpResponse hresp = h.send(req);
responseWrapper wResp =
(responseWrapper) JSON.deserialize(hresp.getBody(), responseWrapper.class);
accToken = wResp.access_token;
instanceurl = wResp.instance_url;
System.debug('accToken' + accToken);
System.debug('instanceurl' +
instanceurl);
return Database.getQueryLocator(query);
}
global void
execute(Database.BatchableContext BC, List < Contact > conList) {
System.debug('Inside Execute Method');
System.debug('accToken' + accToken);
System.debug('instanceurl' +
instanceurl);
System.debug('conListSize' +
conList.size());
for (integer i = 0; i <
conList.size(); i++) {
try {
if (accToken != '') {
string endPoint =
instanceurl + '/services/apexrest/createContactRecordWebservice';
Http h1 = new Http();
HttpRequest req1 = new
HttpRequest();
req1.setHeader('Authorization',
'Bearer ' + accToken);
req1.setHeader('Content-Type', 'application/json');
req1.setMethod('POST');
req1.setEndpoint(endPoint);
system.debug('conList[i]' +
conList[i]);
req1.setBody(JSON.serialize(conList[i]));
HttpResponse hresp1 =
h1.send(req1);
system.debug('hresp1' +
hresp1);
system.debug('hresp1.getStatusCode()'
+ hresp1.getStatusCode());
system.debug('hresp1.getBody()' + hresp1.getBody());
if (hresp1.getStatusCode()
== 200) {
system.debug('Callout
Success');
}
}
} catch (Exception e) {
System.debug('Some error
occured and is : ' + e.getMessage() + 'at line number: ' + e.getLineNumber());
}
}
}
global void
finish(Database.BatchableContext BC) {}
}
Webservice Class
Created in ORG B:
The below Webservice in ORG B will be invoked from the
execute method of the batch class from ORG A. It is expecting First Name, Last Name,
Email in the request body and it will then create contact record.
@RestResource(urlMapping =
'/createContactRecordWebservice/*')
global with sharing class
createContactRecord {
@HTTPPOST
global static boolean insertContact() {
Boolean finalStatus;
RestRequest req = RestContext.request;
system.debug('RestContext.request' +
RestContext.request);
RestResponse res = Restcontext.response;
Map < String, Object > newmap = (Map
< String, Object > ) JSON.deserializeUntyped(req.requestBody.toString());
system.debug('newmap ' + newmap);
String fName = (String)
newmap.get('FirstName');
system.debug('fName' + fName);
String lName = (String)
newmap.get('LastName');
String email = (String)
newmap.get('Email');
Contact con = new Contact();
con.FirstName = fName;
con.LastName = lName;
con.Email = email;
/***Modify the HTTP status code that will
be returned to external system***/
try {
insert con;
res.statuscode = 201;
finalStatus = true;
}
/***Modify the HTTP status code that will
be returned to external system***/
catch (Exception e) {
System.debug('Some error occured and is :
' + e.getMessage() + 'at line number: ' + e.getLineNumber());
finalStatus = false;
}
return finalStatus;
}
}
Now, we will create a CSV file of contact records and will
try to load more than 100 contacts in ORG A to check the batch apex working.
Now, let us try to execute the below code from anonymous window. Note in the below example we are not passing the scope size.
BatchApexCalloutClass
batchObject = new BatchApexCalloutClass();
Id batchId =
Database.executeBatch(batchObject);
As we have loaded more than 100 contact records, and when we
execute the above code from an anonymous window, we will get the error as shown
in the below image. This is because when we do not specify the scope size, 200
is taken as the default, and since we will get more than 100 records in a
batch, the number of callouts will exceed the 100 limit.
Now, let’s specify the scope size as 100 as shown in below
image.
Now, the code will be successfully executed.
As the batch is successfully executed, we can also see the records will be successfully created in ORG B.
No comments:
Post a Comment