Interview Questions on Future Method in Salesforce

Hello everyone, Welcome to SFDC Worlds...!!

Last month I started the "Interview Series on Asynchronous Apex (i.e. Batch Apex, Apex Scheduler, Future Methods and Queueable Apex)". My first and second Interview Series was on Batch Apex and Apex Scheduler.

In this blog series, I am starting next interview series on Future Methods. I am covering real time scenario questions and concepts. I have tried to cover all scenario based questions which are often asked by Salesforce Apex Developer in an interview.

Understanding Asynchronous Apex: Future Method


A future method runs in the background, asynchronously. You can call a future method for executing long-running operations, such as callouts to external Web services or any operation you’d like to run in its own thread, on its own time.

You can also use future methods to isolate DML operations on different sObject types to prevent the mixed DML error. Each future method is queued and executes when system resources become available. That way, the execution of your code doesn’t have to wait for the completion of a long-running operation. A benefit of using future methods is that some governor limits are higher, such as SOQL query limits and heap size limits.



The above image Depicting the difference in thread processing between apex normal transaction and in future method.

The specialty of the Future method is that it executes when the resources are available and does not out overhead on the server. This is the reason that execution of the code does not have to wait for the completion of a long running operation and also we get higher Governor limits when we use Asynchronous Apex.

Syntax:

global class FutureClass {
    @future
    public static void myFutureMethod() {   
         // Perform some operations
    }
}

Some consideration before we start implementing the future method is that it should be declared as a static method and the only return type it can have is void. Secondly, the parameter defined for the future method must be primitive i.e. no salesforce sObject can be passed as a parameter to the future method. The reason an sObject is not passed in the future method is that there is a possibility that the sent sObject might change between the time the future method is executed.

To interact future method with the sObject that already exists in the database, we can pass the ID of the object instead and then fetch the latest version of the record in the method itself and then perform the task, as shown below.

global class FutureClass{
    
    @future
    public static void myFutureMethod(List<ID> recordIds){
         // We can get the records based on the list of Ids
        List<custobj> obj = [SELECT Name FROM custObj WHERE Id IN : recordIds];
        // We can Process records after fetching the records
        
    }
}

Below is a skeletal code of a future method that interacts with an external web service. For this we have to add an extra annotation to the method to make the platform aware that this method will interact with an external service, as shown below

global class FutureClass{
    
    @future(callout=true)
    public static void myFutureMethod(List<ID> recordIds){
         // We can get the records based on the list of Ids
        List<custobj> obj = [SELECT Name FROM custObj WHERE Id IN : recordIds];
        // We can Process records after fetching the records
    }
}


Specify (callout=true) to allow callouts in a future method. Specify (callout=false) to prevent a method from making callouts.


 Key Future Method Considerations

1. Use @future annotation before the method declaration.

2. Future methods must be static methods, and can only return a void type.

3. The specified parameters must be primitive data types, arrays of primitive data types, or collections of primitive data types.

4. Future methods can’t take standard or custom objects as arguments.

5. You can invoke future methods the same way you invoke any other method. However, a future method can’t invoke another future method.

6. No more than 50 method calls per Apex invocation.

7. Asynchronous calls, such as @future or executeBatch, called in a startTest, stopTest block, do not count against your limits for the number of queued jobs.

8. The maximum number of future method invocations per a 24-hour period is 250,000 or the number of user licenses in your organization multiplied by 200, whichever is greater.

9. To test methods defined with the future annotation, call the class containing the method in a startTest(), stopTest() code block. All asynchronous calls made after the startTest method are collected by the system. When stopTest is executed, all asynchronous processes are run synchronously.

10. A common pattern is to pass the method a list of record IDs that you want to process asynchronously.

global class FutureMethodRecordProcessing {
    @future
    public static void processRecords(List<ID> recordIds){   
    // Get those records based on the IDs
    List<Account> accts = [SELECT Name FROM Account WHERE Id IN :recordIds];
    // Process records
    }
}

 Limitations of Future Methods

• It is not a good option to process large numbers of records.

• Only primitive data types supported.

• Tracing a future job is also typical.

• Can’t call future from batch and future contexts, 1 call from queueable context is allowed.


 Interview Series

Hey guys, I have tried to cover Future Method based questions that are often asked from a Salesforce developer in an interview.
Let start the third interview series on Future Method (Between Interviewer & Interviewee).

Interview Series: Future Method


 Interviewer: Why do we use Future Methods?


 Interviewee: You can call a future method for executing long-running operations, such as callouts to external Web services or any operation you would like to run in its own thread, on its own time.
Prevent the mixed DML error.


 Interviewer: Can you write the syntax of a future method?


 Interviewee: Methods with the future annotation must be static methods, and can only return a void type.


global class FutureClass {
    @future
    public static void myFutureMethod() {   
         // Perform some operations
    }
}

 Interviewer: What are the considerations while using future methods?


 Interviewee: 


1. Methods with the future annotation must be static methods.
2. Can only return a void type.
3. The specified parameters must be primitive data types, arrays of primitive data types, or collections of primitive data types.

Notably, future methods can’t take standard or custom objects as arguments. You can pass the List of record IDs that you want to process asynchronously.


 Interviewer: What kinds of parameters supported in Future methods?


 Interviewee: You can pass primitive data types, arrays of primitive data types, or collections of primitive data types as parameters. No sObjects OR objects as arguments can be passed.


 Interviewer: Why sobject type parameters are not supported in Future methods?


 Interviewee: The reason why sObjects can’t be passed as arguments to future methods is that the sObject might change between the time you call the method and the time it executes. In this case, the future method will get the old sObject values and might overwrite them.


 Interviewer: Can we fix the order in which future methods will run?


 Interviewee: Future methods are not guaranteed to execute in the same order as they are called. When using future methods, it’s also possible that two future methods could run concurrently, which could result in record locking.


 Interviewer: How to call Future methods from Process Builder?


 Interviewee: To call Future methods from Process Builder, call the future method from the invocable method.



 Interviewer: What could be the workaround for sobject types?


 Interviewee: To work with sObjects, pass the sObject ID instead (or collection of IDs) and use the ID to perform a query for the most up-to-date record.

global class FutureMethodRecordProcessing {
    @future
    public static void processRecords(List<ID> recordIds){   
    // Get those records based on the IDs
    List<Account> accts = [SELECT Name FROM Account WHERE Id IN :recordIds];
    // Process records
    }
}

 Interviewer: How can I perform Callouts from Future methods?


 Interviewee: To allow callout from the future method annotation needs an extra parameter (callout=true) to indicate that callouts are allowed. 

Here is example:

global class FutureMethodExample {
    @future(callout=true)
    public static void getStockQuotes(String acctName){
        // Perform a callout to an external service
    }
}

 Interviewer: How Can I call a future method?


 Interviewee: You can invoke future methods the same way you invoke any other method.


FutureMethodExample.doCallouts('Account');

 Interviewer: Can I Write the Above statement in a Batch Job?


 Interviewee: No you can’t, because Calling a future method is not allowed in the Batch Jobs.



 Interviewer: Can I write a future call in Trigger?


 Interviewee: Yes, you can.



 Interviewer: From which places we can call future method?


 Interviewee: We can call future method in following places: 


• Trigger
• Apex Class
• Schedulable Class


 Interviewer: So, consider a case, I have Written a future call in the Account’s trigger update operation. and I have a batch job running on Account records and does DML on them. Will the future call be invoked after DML?

 Interviewee: Since you are in batch context, the trigger runs in the same context too, So as soon as the Account records get updated through the batch process or through any future method, the trigger would throw an exception saying “Future method cannot be called from a future or batch method” as a future method cannot be invoked from future or batch method execution context.


 Interviewer: How can avoid this Exception condition, Without using try-catch?


 Interviewee: We can update the trigger logic to leverage the System.isFuture() and System.isBatch() calls so that the future method invocation is not made if the current execution context is future or batch.

trigger AccountTrigger on Account (after insert, after update) {
if(!System.isFuture() && !System.isBatch())
// future call
}

 Interviewer: So In Any case, I can’t call a future method from a batch Job?


 Interviewee: Calling a future method is not allowed in the Execute method, But a web service can be called. A web service can also call an @future method. So, we can define a web service having a future method invocation and call the web service from the execute method of Batch Job.


 Interviewer: How Many Future methods can be defined in a Class?


 Interviewee: Any number of. There are no restrictions as such.



 Interviewer: Take the below case,


global class FutureMethodExample
{
    @future(callout=true)
    public static void doCallouts(String name)
    {   
         // Perform a callout to an external service
         doCallouts2(name);
}
@future
    public static void doCallouts2(String name)
    {   
         // Perform a callout to an external service
    }
}

How many future calls will the above code invoke?

 Interviewee: This code is an invalid code as a future method can’t invoke another future method.


 Interviewer: If I want to call a future method from a future method, what could be the solution?


 Interviewee: Workaround could be calling a web service that has future invocation.



 Interviewer: What are the other use cases of using a future method?


 Interviewee: We can also use future methods to isolate DML operations on different sObject types to prevent the mixed DML error.



 Interviewer:What is a Mixed DML error?


 Interviewee: There are 2 kinds of sObjects in salesforce.


1. Non-Setup: Account, opportunity, etc

2. Setup: User, groups, etc

In a single transaction Or execution context, If you are performing DML on both kinds, the system doesn’t allow it and throws an exception called Mixed DML exception, stating that a transaction can not have Mixture of DML operation(Setup and Non-Setup).


 Interviewer: How Future method helps in avoiding Mixed DML errors?


 Interviewee: We can shift DML operations of a particular kind in the Future scope. Since both the DML operations are isolated from each other, the transaction doesn’t fail.

For example:

public class MixedDMLFuture {
    public static void useFutureMethod() {
        // First DML operation
        Account acc = new Account(Name='Acme');
        insert acc;
        
        // This next operation (insert a user with a role) 
        // can't be mixed with the previous insert unless 
        // it is within a future method. 
        // Call future method to insert a user with a role.
        Util.insertUserWithRole(
            'learnfrenzy.com', 'Test1', 
            'learnfrenzy.com', 'Test2');        
    }
}

 Interviewer: Once I call a future method, How can I trace its execution?


 Interviewee: Salesforce uses a queue-based framework to handle asynchronous processes from such sources as future methods and batch Apex. So, We can check the apex jobs if it has run or not.

But if it in the queue, and resources are not available, It won’t show up on Apex jobs Page, So we can poll AsyncApexJob object to get its status.

However, future methods don’t return an ID, so We can’t trace it directly. We can use another filter such as MethodName, or JobType, to find the required job.


 Interviewer: How to test a future method?


 Interviewee: To test methods defined with the future annotation, call the class containing the method in a startTest(), stopTest() code block. All asynchronous calls made after the startTest method are collected by the system. When stopTest is executed, all asynchronous processes are run synchronously.

@isTest
private class MixedDMLFutureTest {
    @isTest static void test1() {
        User thisUser = [SELECT Id FROM User WHERE Id = :UserInfo.getUserId()];
       // System.runAs() allows mixed DML operations in test context
        System.runAs(thisUser) {
            // startTest/stopTest block to run future method synchronously
            Test.startTest();        
            MixedDMLFuture.useFutureMethod();
            Test.stopTest();
        }
        // The future method will run after Test.stopTest();
     
        // Verify account is inserted
        Account[] accts = [SELECT Id from Account WHERE Name='Acme'];
        System.assertEquals(1, accts.size());
        // Verify user is inserted
        User[] users = [SELECT Id from User where username='[email protected]'];
        System.assertEquals(1, users.size());
    }
}

 Interviewer: What are some limitations of future methods?


 Interviewee: Some of the limitations are :


1. It is not a good option to process large numbers of records.

2. Only primitive data types supported.

3. Tracing a future job is also typical.

4. Can’t call future from batch and future contexts, 1 call from queueable context is allowed.


 Interviewer: Can we pass wrapper to future method?


 Interviewee: You can pass wrapper, but for that, you’ll need to serialize/deserialize that parameter. You can convert the Wrapper to a String which is a primitive.

Once converted into a String you can them pass that string as a parameter to the future method in consideration.


  Things to Remember

Things to Remember when using @future annotation

Hey guys, here i am sharing some important questions, those are based on Future Methods , which are very helpful in interviews and things to remember when using @future annotation.

1. Future method should return void and it should be declared as static.

2. Can we pass objects as a parameter to the future method? 

No, we cannot pass the objects (custom, standard) as parameter. We can only pass the Id’s as a parameter, primitive data type or collection of primitive data types as a parameter.

3. Why we cannot pass the object (custom, standard) as a parameter? 

Remember we are working with asynchronous apex they will execute only when the resources are available so if we use the object as a parameter then the system will not hold the current data.

4. Did future method execute in the same order they called? 

The answer is no, as they are not guaranteed to execute in the same order. So, can we call it a limitation? Yes, we can overcome this by using the queueable apex.

5. Will future methods run concurrently which means updating the same record by 2 future methods at a same time from different sources or the same source? 

Yes, and which could result in locking the record. so, need to incredibly careful while dealing with future methods.

6. Do I have to take any special care while writing the test class for future methods?

Yes, you need to enclose the code between start and stop test methods.

7. Can I use future method for bulk transactions? 

The answer will not be likeable, but it is good to avoid future and good to use batch processing.

8. What is the limit on future calls per apex invocation? 

50, additionally there are limits base on the 24-hour time frame.

9. Can we user future method in visual force controller constructors? 

The answer is no.

10. Can I call a future method from another future method? 

No, you cannot call one future method from another future method.


Hopefully, this interview series on Future Method will help to understand Future Method clearly and crack the interview.

All the Best...!!   

For more details please refer to official link

Share This Post:

About The Author

Hey, my name is Saurabh Samir and I am Salesforce Developer. I have been helping to elevate your Salesforce Knowledge. Do comment below if you have any questions or feedback's.