Introduction to Batch Apex + Examples

Share this article...

Introduction

For business scenarios which require the platform to process more than 50000 records, Batch Apex comes to the rescue. Batch Apex facilitates asynchronous processing of the records in multiple batches or chunks and is straightforward to implement for a developer.

Implementing Batch Apex

Batch Apex implements the Database.batchable interface. The interface has Start(), Execute() and Finish() methods which should be implemented in the Batch Apex class.

  1. Startmethod: Start method is a collection point for the records to be processed in the execute method of the batch apex
  2. Execute method: The actual processing of the records takes place in the execute method.
  3. Finish method: Finish methods can have post job processing actions like sending the emails or it can also be used to chain another batch class.

Scheduling the Batch Apex

Method 1: Using OOTB Schedule Apex functionality

Steps:

  1. Click on Setup and search for Apex Classes in the quick find box.
  2. Click on the Schedule Apex button at the top panel.

3. Fill in the information on the Schedule Apex record page and Save. The apex class should be the Scheduler class implementing the executebatch(batch) method.

Code Snippet for the Scheduler Class:

global class AccBatchScheduleClass implements Schedulable {    
global void execute(SchedulableContext ctx) {
    AccBatchApex batch = new AccBatchApex();
    database.executebatch(batch);
  
     }
}

Method 2:  Invoking Batch Class via Schedulable Apex:

The Apex class should be created which should implement the Schedulable apex. The Schedulable apex must implement System.Schedule() method to enqueue the batch apex in the execution queue. The System.Schedule() method expects three arguments viz Job Name, Cron expression for the batch schedule and the batch class name.

Sample Schedulable Apex:

global class AccBatchScheduleClass implements Schedulable {    
global void execute(SchedulableContext ctx) {
	AccBatchApex accCls = new AccBatchApex();
	String cronStr = '20 30 8 10 2 ?';
	String jobID = System.schedule('Process Acc Records', cronStr, accCls);   
	 }
}

Batch Apex Chaining

With the onset of API version 29.0 and after, a batch class can be chained to another batch class. Chaining of batch apex kickstarts the execution of the chained batch class once the execution of the base batch class is finished. At maximum, only 5 Batch jobs can be chained to one another. Sample code snippet for chaining the batch Apex is illustrated below:

 
global database.querylocator start(Database.BatchableContext BC)
{
  //start method logic here
}

global void execute(Database.BatchableContext BC, List<sObject> scope)
 {
    //start method logic here
}

global void finish(Database.BatchableContext BC)
 {
       //Batch Chaining Step Starts here
       AccountBatch accBatch = new AccountBatch ();
      Id batchProcessId = Database.executeBatch(accBatch);
    
 	//finish method logic here

}

Batch Apex Example

Use Case: Populate the Billing State as California for all the Accounts with Country as USA and no Billing State information.

Solution Design: The org has more than 50K records which need to be skimmed for the missing Billing State information so writing the Batch Apex is the optimum solution. Also Triggers, Workflows, Process Builders etc. will need a DML operation to fire so these solutions do not fit to meet the business requirement.

global class UpdateAccountBillingState implements Database.Batchable<sObject>, Database.Stateful {
    global Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator(
            'SELECT ID,BillingState,BillingCountry FROM Account Where BillingCountry =\'USA\' AND BillingState =\'\'' 
        );
    }
    global void execute(Database.BatchableContext bc, List<Account> scope){
        // process each batch of record
        List<Account> lstAccount = new List<Account>();        
        for (Account acc : scope) {
            acc.BillingState = 'California';
            lstAccount.add(acc);   
        }    
        update lstAccount;
    }    
    global void finish(Database.BatchableContext bc){
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
      
      // Use the
      AsyncApexJob a = [Select a.TotalJobItems, a.Status, a.NumberOfErrors,
      a.JobType, a.JobItemsProcessed, a.ExtendedStatus, a.CreatedById,
      a.CompletedDate From AsyncApexJob a WHERE id = :BC.getJobId()];
      
      // below code will send an email to User about the status
      String[] email = new String[]{'.com'};
      mail.setToAddresses(email);
      mail.setReplyTo('[email protected]'); // Add here your email address
      mail.setSenderDisplayName('Apex Batch Processing Module');
      mail.setSubject('Batch Processing '+a.Status);
      mail.setPlainTextBody('The Batch Apex job processed '+ a.TotalJobItems+'batches with '+a.NumberOfErrors+'failures '+'Job Itemprocessed are '+a.JobItemsProcessed);
      Messaging.sendEmail(new Messaging.Singleemailmessage [] {mail});
    }    
    
}

Things to remember

  • Up to 5 batch jobs can be queued or active concurrently.
  • The maximum number of batch Apex method executions per 24-hour period is 250,000, or the number of user licenses in your org multiplied by 200—whichever is greater.
  • A maximum of 50 million records can be returned in the QueryLocator object. If more than 50 million records are returned, the batch job is immediately terminated and marked as Failed.
  • If the startmethod of the batch class returns a QueryLocator, the optional scope parameter of executeBatch can have a maximum value of 2,000.
  • If the start method of the batch class returns an iterable, the scope parameter value has no upper limit.
  • The start, execute, and finish methods can implement up to 100 callouts each. Implement AllowsCallouts for enabling callouts from the Batch apex.
  • Methods declared as future can’t be called from a batch Apex class.
  • All methods in the class must be defined as global or public.

Optimizing Your Implementation

  • Batch Apex jobs run faster when the startmethod returns a QueryLocator object that doesn’t include related records via a subquery. Avoiding relationship subqueries in a QueryLocator allows batch jobs to run using a faster, chunked implementation.
  • To ensure fast execution of batch jobs, minimize Web service callout times and tune queries used in your batch Apex code.
  • For each 10,000 AsyncApexJobrecords, Apex creates an AsyncApexJob record of type BatchApexWorker for internal use. When querying for all AsyncApexJob records, we recommend that you filter out records of type BatchApexWorker using the JobType
  • For a sharing recalculation, we recommend that the execute method delete and then re-create all Apex managed sharing for the records in the batch. This process ensures that sharing is accurate and complete.
  • Use the Test methods startTest and stopTest around the executeBatch method to ensure that it finishes before continuing your test.

One thought on “Introduction to Batch Apex + Examples

Leave a Reply