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.
global class
FutureClass {
@future
public
static void myFutureMethod()
{
// Perform some operations
}
}
KEY
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.
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.
Can we fix the order in which future methods will run?
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.
How to call Future methods from Process Builder?
call the future method from the invocable
method.
How can I perform Callouts from Future methods?
To allow callout use (callout=true) to
indicate that callouts are allowed.
|
|
global class
FutureMethodExample { @future(callout=true) public
static void getStockQuotes(String acctName){ // Perform a callout to an external service } } |
How Can I call a future method?
You can invoke future methods the same
way you invoke any other method.
|
FutureMethodExample.doCallouts('Account'); |
Can I
Write the Above statement in a Batch Job?
No you can’t, because Calling a future
method is not allowed in the Batch Jobs.
Can I write a future call in Trigger? - Yes, you can.
From which places we can call future method?
• Trigger
• Apex Class
• Schedulable Class
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?
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 } |
How Many Future methods can be defined in a Class? - no restrictions
|
|
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.
|
|
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'); } } |
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?
|
|
@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='mruiz@awcomputing.com']; System.assertEquals(1, users.size()); } } |
Can we pass wrapper to future method?
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.
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.
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.
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.
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.
What is the limit on future calls per apex invocation?
50, additionally there are limits base on the 24-hour time
frame.
Can we user future method
in visual force controller constructors? - NO
Can I call a future method from another future method? - No
No comments:
Post a Comment