Future Method in Apex

In this article, we will discuss

  • What is future method
  • Why should we learn about future method
  • Scenarios when future method has to be used
  • Limitations of future method

Synchronous Task

  • Brush Teeth
  • Eat breakfast
  • Put dirty clothes in laundry
  • Study Salesforce

It is performing one job at a time and only when current job is completed we can do other work.

Asynchronous Process:

It is process of making task run in the background. i.e. I can put dirty clothes in laundry and meanwhile perform another task like studying Salesforce.

In technical terms, asynchronous is something which runs in background without having to wait for that task to finish.

Conclusion:

Things that does not need user interaction like button click, giving input can be moved to Asynchronous.

Why we need Asynchronous process

  1. Not to wait for jobs that does not need my attention
  2. Higher Limits: Asynchronous jobs were given higher limit

Example- 200 SOQL instead of 100 SOQL

Future method

It is set of code that runs in background. The four task we discussed in Salesforce Analogy we can take them as four methods

brushTeeth(){}

eatBreakfast(){}

clothesInLaundry(){}

studySalesforce(){}

If we want any method to run in future, put @future annotation. This way Salesforce understands that this method needs to run asynchronously.

@future
public static void clothesInLaundry(){
}

Void – As it runs in future so it does not return any value to you currently

The specified parameters must be primitive data types, arrays of primitive data types, or collections of primitive data types; future methods can’t take objects as arguments.

Eg: – Integer, Boolean, List<Id>

The reason why objects can’t be passed as arguments to future methods is because the object can change between the time you call the method and the time that it actually executes. Remember, future methods are executed when system resources become available. In this case, the future method may have an old object value when it actually executes, which can cause all sorts of bad things to happen.

How to call future method?

ClassName.clothesInLaundry();

Scenarios when we use future method:

Scenario 1: Whenever we want our code to be run in background

Scenario 2: You must have faced DML exception. This exception occurs when we insert setup and non setup objects in one transaction.

Setup: User, Group, Profile,Layout, Email Template

Non Setup: All other standard and custom objects (Account, Custom Objects)

In same context, we cannot insert User/Profile and Account in same object. Future method helps in this situation.

Scenario 3: We cannot perform callout from trigger. Use future method to put callout in future method to make a callout.

Limitations of Future method:

  1. You cannot call one future method from another method
  2. Can have only primate as parameters
  3. Order of Invocation is not respected
  4. Cannot invoke future method from another future method

Interview Questions on Future Method

Why do we use Future Methods?

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.

Can you write the syntax of a future method?

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
}
}

What kinds of parameters supported in Future methods?

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.

Why sobject type parameters are not supported in Future methods?

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.

What could be the workaround for sobject types?

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
// Process records
}
}

We need to add a parameter callout=true in @future.

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

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

FutureMethodExample.doCallouts('Account');

Can I write a future call in Trigger?

Yes, you can.

 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?

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.

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

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}

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

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.

 How Many Future methods can be defined in a Class?

Any number of. There are no restrictions as such.

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?

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

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

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

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

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

What is a Mixed DML error?

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)

How Future method helps in avoiding Mixed DML errors?

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 a = new Account(Name='Acme');
insert a;

// 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(
'abc.com', 'Test',
'acb.com', 'Test2');
}
}

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

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.

How to test a future method?

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.

What are some limitations of future methods?

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.
Did you enjoy this article?
Signup today and receive free updates straight in your inbox.
I agree to have my personal information transfered to MailChimp ( more information )
50% LikesVS
50% Dislikes