Why use Database.stateful in Batch Apex

Each execution receives a new copy of variables and objects in the Batch apex. Since the batch class is stateless by default. It is impossible to utilize past execution values in a new execution. Consequently, static variables lose their value over time.

Therefore, we need to create a database if we wish to use variables that keep their values and use them in the execution and complete methods. stateful as defined by the class.

Related Post: How To Create Lightning Flows In Salesforce – Step By Step Guide

How To Use Database.Stateful Interface In Batch Apex In Salesforce

To utilize Batch Apex, we must first comprehend that we must create an Apex Class that implements the Salesforce-provided interface Database. Batchable, then programmatically call the class. Enter “Apex Jobs” in the Quick Find box under Setup to monitor or halt the execution of the batch Apex task. Then, select Apex Jobs.

The Syntax for Batch

global class BatchName implements Database.Batchable{}

Methods of Batch Class:

global (Database.QueryLocator | Iterable) start (Database.BatchableContext bc) {
 //Here we will add the query and return the result to execute method
}

global void execute (Database.BatchableContext BC, list<P>){
 //Logic must be here
}

global void finish (Database.BatchableContext BC){
 //after processing of all batches this method will be called. We can write any code inside it. Like if want to send email to all the records which are created or updated in the execute method.
}

How to Implement the Database.Batchable Interface

Example

global class BatchAccountUpdate implements Database.Batchable{
    String query = 'Select Name from Account WHERE Name! = null AND (Name = \'Virendra Company\' OR Name = \'Virendra Sharma\') ';
    global Database.QueryLocator start (Database.BatchableContext bc) {
        // collect the batches of records or objects to be passed to execute
        return Database.getQueryLocator(query);
    }

    global void execute (Database.BatchableContext bc, List records) {
        // process each batch of records
        for (Account acc : records){
            acc.Name = acc.Name + '  Updated';
        }
        update records;
    }

    global void finish (Database.BatchableContext bc){
        // execute any post-processing operations, Calling batch class.
        BatchUpdateAccountRelatedContacts b = new BatchUpdateAccountRelatedContacts();
        Database.executeBatch(b, 200);
    }
}
Database.Stateful In Batch Apex

Database.Stateful

The subsequent sample class uses a QueryLocator to locate all the account data given by the start() function and then changes the related contacts with the postal address of their respective accounts. Since we are utilizing a database.stateful, it then sends an email with the results of the bulk process to track the number of updated records and the state.

Example:

global class UpdateContactAddresses implements
Database.Batchable<sObject>, Database.Stateful {
// instance member to retain state across transactions
global Integer recordsProcessed = 0;
global Database.QueryLocator start (Database.BatchableContext bc) {
return Database.getQueryLocator(
'SELECT ID, BillingStreet, BillingCity, BillingState, ' +
'BillingPostalCode, (SELECT ID, MailingStreet, MailingCity, ' +
'MailingState, MailingPostalCode FROM Ccntacts) FROM Account' +
'Where BillingCountry =
global void execute (Database.BatchableContext bc, List<Account> scope){
// process each batch of records
List<Contact> contacts = new List<Contact>O;
for (Account account : scope) {
for (Contact contact : account.contacts) {
contact.MailingStreet = account.BillingStreet;
contact.MailingCity = account.BillingCity;
contact.MailingState = account.BillingState;
contact.MailingPostalCode = account.BillingPostalCode;
// add contactto list to be updated
contacts.add(contact);
// incrementthe instance member counter
recordsProcessed = recordsProcessed + 1;
update contacts;
global void finish (Database.BatchableContext bc){
System.debug(recordsProcessed + ' records processed. Shazam!');
AsyncApexJob job = [SELECT ld, Status, NumberOfErrors,
JobltemsProcessed,
TotalJobItems, CreatedBy.Email
FROM AsyncApexJob
WHERE ld = :bc.getJ0bldO];
// call some utility to send email
EmailUtils.sendMessage(job, recordsProcessed);

Database.AllowsCallout

Database. AllowsCallout in Batch facilitates the connection of Salesforce to a remote or external server. To use a callout in batch Apex, We need to utilize an interface Database. AllowsCallouts in the batch class’s class definition.

The Syntex

global class SearchAndReplace implements Database.Batchable, Database.AllowsCallouts{}

Example:
Here, We are integrating the Opportunity object with Skedulo.com
/*
Get service requests from Skedulo and update them in the salesforce.
*/

global class Batch_SR_SkeduloAPI implements Database.Batchable, Database.AllowsCallouts{
    global Database.QueryLocator start (Database.BatchableContext BC){
        String query = 'SELECT Id, Octalsoftware_Service_Request_Id__c FROM Opportunity WHERE Skedulo_Service_Request_Id__c != null AND Skedulo_Job_Status__c != \'Job Done\' AND Skedulo_Status__c = \'Success\'';
        return Database.getQueryLocator(query);
    }

    global void execute (Database.BatchableContext BC, List scope){
        String StatusId = '';
        for (Opportunity s : scope){
            //get ServiceRequest
            System.debug(s.Id);
            Http http1 = new Http();
            HttpRequest request1 = new HttpRequest();
            request1.setEndpoint('https://DomainName.0.Skedulo.com/ApiService.svc/ServiceRequest/'+ s.Skedulo_Service_Request_Id__c);
            request1.setMethod('GET');
            request1.setHeader('Content-Type', 'application/json');
            request1.setHeader('Host', 'DomainName.0.Skedulo.com');
            request1.setHeader('Content-Length', '0');
            request1.setHeader('Connection', 'Keep-Alive');
            request1.setHeader('ServerName', 'DomainServerName');
            request1.setHeader('Token', 'XXXXXXXXXXXXXXXXXXXXXXX');

            HttpResponse response1 = http1.send(request1);

            if(response1.getStatusCode() == 200) {
                StatusId = '';
                JSONParser parser = JSON.createParser(response1.getBody());
                while(parser.nextToken() != null) {
                    if( (parser.getCurrentToken() == JSONToken.FIELD_NAME) && (parser.getText() == 'StatusId') || Test.isRunningTest()) {
                        parser.nextToken();
                        StatusId = parser.getText();
                    }
                }
                System.debug(StatusId);
                if(StatusId == String.valueOf(1) || Test.isRunningTest()){
                    s.Skedulo_Job_Status__c = 'Job Done';
                    s.StageName = 'Closed Won';
                }else{
                    s.Skedulo_Job_Status__c = 'Working';
                }
            }
        }
        update scope;
    }
    global void finish (Database.BatchableContext BC){
    }
}

And this is how we use Database.Stateful In Batch Apex.

Looking for salesforce consulting services? Let’s connect and discuss your exciting project.

THE AUTHOR
Managing Director
WebisteFacebookInstagramLinkedinyoutube

Arun Goyal is a passionate technology enthusiast and a seasoned writer with a deep understanding of the ever-evolving world of tech. With years of experience in the tech industry, Arun has established himself as a prominent figure in the field, sharing his expertise and insights through his engaging and informative blog posts.

Previous Post Next Post

Octal In The News

Octal IT Solution Has Been Featured By Reputed Publishers Globally

Let’s build something great together!

Connect with us and discover new possibilities.

    Gain More With Your Field Service

    We’re always keeping our finger on the pulse of the industry. Browse our resources and learn more.

    Let's schedule a call
    Mobile App Development
    Mobile App Development Mobile App Development