Calling Asynchronous Processes from Asynchronous Processes in Apex Salesforce

Oct 16, 2023


 

 

After completing this unit, you’ll be able to:

 

Introduction:

This blog post dives into the world of asynchronous processing in Apex Salesforce, specifically focusing on how to call asynchronous processes from within other asynchronous processes. You'll gain a clear understanding of the possibilities and limitations associated with this approach.

 

Asynchronous Processing in Apex

Asynchronous processing in Apex allows you to execute long-running tasks in the background, without blocking the main user interface or transaction. This is particularly useful for tasks that might take a significant amount of time, such as:

 

Call Asynchronous Process from Asynchronous Process in Apex

S.No. From (Calling Process) To (Called Process) Supported?
1. Batch (Start Method) Batch No
2. Batch (Execute Method) Batch No
3. Batch (Finish Method) Batch Yes
4. Batch (Start Method) Queue Yes
5. Batch (Execute Method) Queue Yes
6. Batch (Finish Method) Queue Yes
7. Batch (Start Method) Future No
8. Batch (Execute Method) Future No
9. Batch (Finish Method) Future No
10. Batch (Start Method) Schedule Yes
11. Batch (Execute Method) Schedule Yes
12. Batch (Finish Method) Schedule Yes
13. Future Future No
14. Future Batch No
15. Future Queue Yes
16. Future Schedule Yes
17. Queue Queue Yes
18. Queue Batch Yes
19. Queue Future Yes
20. Queue Schedule Yes
21. Schedule Schedule Yes
22. Schedule Batch Yes
23. Schedule Future Yes
24. Schedule Queue Yes

 

Some Examples:

 

1. Calling Batch Class from Batch(Start Method):

Batch Class 1:

BatchClassTest1.apxc
public class BatchClassTest1 implements DataBase.Batchable<sObject> {
    public Database.QueryLocator start(Database.BatchableContext bc) {
        System.debug('BatchClassTest1 start called.');
        //batch calling
        DataBase.executeBatch(new BatchClassTest2());
        String accountQuery = 'SELECT Id, Name FROM Account LIMIT 1';
        return Database.getQueryLocator(accountQuery);
    }
   
    public void execute(Database.BatchableContext bc, List<Child_Object__c> childs) {
        System.debug('BatchClassTest1 execute called.');
    }
   
    public void finish(Database.BatchableContext bc) {
        System.debug('BatchClassTest1 finish called.');
    }
}
 

BatchClass 2:

BatchClassTest2.apxc
public class BatchClassTest2 implements DataBase.Batchable<sObject> {
  public Database.QueryLocator start(Database.BatchableContext bc) {
        System.debug('BatchClassTest2 start called.');
        String accountQuery = 'SELECT Id, Name FROM Account LIMIT 1';
        return Database.getQueryLocator(accountQuery);
    }
   
    public void execute(Database.BatchableContext bc, List<Child_Object__c> childs) {
        System.debug('BatchClassTest2 execute called.');
    }
   
    public void finish(Database.BatchableContext bc) {
        System.debug('BatchClassTest2 finish called.');
    }
}
 
When we execute "DataBase.executeBatch(new BatchClassTest1());" from an anonymous window, then the BatchClassTest2 class cannot be called and an error comes.

 

2. Calling Queue Class from Future Method:

Future Class:

FutureTest1.apxc
public class FutureTest1 {
    @future
    public static void testFutureMethod1() {
        System.debug('testFutureMethod1 called.');
        //queue calling
        System.enqueueJob(new QueueTest1());
    }
}
 
Queue Class:
 
public class QueueTest1 implements Queueable {
    public void execute(QueueableContext qc) {
        System.debug('QueueTest1 execute called.');
    }
}
 
 
When we execute "FutureTest1.testFutureMethod1();" from an anonymous window, then the QueueTest1 class can be called. 

 

3. Calling Batch Class from Queue Class:

Queue Class:

QueueTest2.apxc
public class QueueTest2 implements Queueable {
    public void execute(QueueableContext qc) {
        System.debug('QueueTest2 execute called.');
        //batch calling
        DataBase.executeBatch(new BatchClassTest3());
    }
}

 

Batch Class:

BatchClassTest3.apxc
public class BatchClassTest3 implements DataBase.Batchable<sObject> {
  public Database.QueryLocator start(Database.BatchableContext bc) {
        System.debug('BatchClassTest3 start called.');
        String accountQuery = 'SELECT Id, Name FROM Account LIMIT 1';
        return Database.getQueryLocator(accountQuery);
    }
   
    public void execute(Database.BatchableContext bc, List<Child_Object__c> childs) {
        System.debug('BatchClassTest3 execute called.');
    }
   
    public void finish(Database.BatchableContext bc) {
        System.debug('BatchClassTest3 finish called.');
    }
}
 

When we execute "System.enqueueJob(new QueueTest2());" from an anonymous window, then the BatchClassTest3 class can be called.

 

4. Calling Future Method from Schedule Class:

Schedule Class:

ScheduleTest1.apxc
global class ScheduleTest1 implements Schedulable {
    global void execute(SchedulableContext SC) {
        System.debug('ScheduleTest1 execute called.');
        // Future method calling
        FutureTest2.testFutureMethod2();
   }
}

 

Future Method:

FutureTest2.apxc
public class FutureTest2 {
    @future
    public static void testFutureMethod2() {
        System.debug('testFutureMethod2 called.');
    }
}
 

When we execute "System.schedule('Test Job', '0 32 13 15 10 ? 2024', new ScheduleTest1());" from an anonymous window, then the FutureTest2 class can be called.

Note:- Customized CRON expression according to you.