Salesforce Hacks: Call a batch class from execute method of another batch class

If we talk about chaining of batch classes, Salesforce provides a way to chain batch classes by calling a batch class from finish method of another batch class. For example, if you have a requirement to call Batch2 from Batch1, then in the finish method of Batch1, you can call Batch 2 as shown below:

// Finish method of Batch1
global void finish(Database.BatchableContext BC) {
    Database.executeBatch(new Batch2(), 1);
}


Recently, I had a requirement in which I need to call Batch2 from execute method of Batch1 as shown below:

// Execute method of Batch1
global void execute(Database.BatchableContext BC, List<Account> scope) {
        Database.executeBatch(new Batch2(), 1);
}


With this code, when Batch1 runs, Salesforce will throw you below exception:

System.AsyncException: Database.executeBatch cannot be called from a batch start, batch execute, or future method.

To bypass this error, we need to create a Queueable class and then enqueue this Queueable class from the execute method of Batch1. In the execute method of Queueable class, you can then call Batch2 and in this case Salesforce will not throw any exception. Below is the sample code:

Batch1:

global class Batch1 implements Database.Batchable<sObject> {
    
    global Database.QueryLocator start(Database.BatchableContext BC) {
        String query = 'SELECT Id FROM Account';
        return Database.getQueryLocator(query);
    }
    
    global void execute(Database.BatchableContext BC, List<Account> scope) {
        System.enqueueJob(new Queueable1());
    }   
    
    global void finish(Database.BatchableContext BC) {
       // logic here
    }
}

 
Queueable class:

public class Queueable1 implements Queueable{

    public void execute(QueueableContext context){
        Database.executeBatch(new Batch2(),1);
    }
}

 
Batch2:

global class Batch2 implements Database.Batchable<sObject> {
    
    global Database.QueryLocator start(Database.BatchableContext BC) {
        String query = 'SELECT Id FROM Contact';
        return Database.getQueryLocator(query);
    }
    
    global void execute(Database.BatchableContext BC, List<Contact> scope) {
        // logic here
    }   
    
    global void finish(Database.BatchableContext BC) {
        // logic here
    }
}

Comments

Popular posts from this blog

Salesforce Lightning: Countdown timer

Salesforce Hacks: System.LimitException: Too many queueable jobs added to the queue: 2

Building an Org Role Hierarchy component in LWC