Recursive Triggers In Salesforce

top, salesforce, blog., apex trigger recursion trigger

Recursive Triggers In Salesforce

In the previous episode, we have discussed how to write triggers in different scenarios based on different trigger events in salesforce.

Now in this episode, we will discuss how and when you need to write recursive triggers in salesforce.
So let's get started...

Recursive Trigger
When you want to write a trigger that creates a new record as part of its processing logic. However, that record may then cause another trigger to fire, which in turn causes another to fire, and so on. You don't know how to stop that recursion.

Using a static variable in an Apex class to avoid an infinite loop. A static variable is local to the context of a web request (or test method during a call to runTest()), so all triggers that fire as a result of a user's action which has access to it.

Let's understand some scenarios...

Scenario :
Suppose there is a scenario where one trigger perform an update operation, which results in invocation of the second trigger and the update operation in second triggers acts as triggering criteria for triggers one.

Apex Class :
============================================
public class utility
{
 public static boolean isFutureUpdate;
}
============================================

Apex Class 2 :
============================================
public class FutureMethods
{
  @future
 public static void processLargeAccounts(set<Id> accIds)
 {
  List<Account> accToUpdate = new List<Account>();
/* isFutureUpdate is set to turn to avoid recurssion */
  utility.isFutureUpdate = true;
  update accToUpdate;
 }
}
============================================

Trigger :
============================================
trigger updateSomething on Account(after insert, after update)
{
 /*This trigger performs its logic when the call is not from @future*/
 if(utility.isFutureUpdate != true)
    {
        set<Id> idsToProcess = new Set<Id>();
        for(Account acc : trigger.new)
        {
            if(acc.NumberofEmployers > 500)
            {
                 idsToprocess.add(acc.Id);                    
            }
        }
        /* Sending Ids to @future method for processing*/
        FutureMethods.processLargeAccounts(idsToprocess);
    }
  }
} 
============================================

In the above scenario, it will first check utility.isFutureUpdate != true from utility class. If it is false that means, a call is not from the future method then it will perform its logic.

Then it will send its Ids to the FutureMethods class to process further.

Now let's have look at another scenario where we will generate recursive trigger error to understand about when exactly you will get recursive trigger error.

So let's get started...

Error Scenario :

Trigger :
============================================
trigger Recursive on Account(after insert, after update)
{
    if(trigger.isAfter && Trigger.isInsert)
    {
        Account acc = [SELECT id, Name FROM Account WHERE Name =                                        'SalesforceKid' LIMIT 1];
        acc.Name = 'New SalesforceKid';
        update acc;
    }
    
    if(Trigger.isAfter && Trigger.isUpdate)
    {
        Account a = new Account(Name = 'Ajinkya');
        insert a;       
    }
}
============================================

The above trigger would generate Recursive trigger error as when you try to update one account record it will call after update trigger on Account object, which would insert a new record into Account object. Which in turn again call After update trigger on Account object. This would continue recursively.

To avoid Recursive trigger error we will use a static variable.
============================================
global class TriggerRuc
{
 global static boolean flag=false;
}
============================================

Now we will set a flag to which will control when to fire the trigger 
Let's take another example with flag

Trigger :
============================================
trigger Recursive on Account(after insert, after update)
{
    if(TriggerRuc.flag != true) //flag check
    {
    if(trigger.isBefore && Trigger.isInsert)
    {
       TriggerRuc.flag = true; //flag set
        Account acc = [SELECT id, Name FROM Account WHERE Name =                                       'SalesforceKid' LIMIT 1];
        acc.Name = 'New SalesforceKid';
        update acc;
    }
    
    if(Trigger.isAfter && Trigger.isUpdate)
    {
        Trigger.flag = true;  //flag set
        Account a = new Account(Name = 'Ajinkya');
        insert a;
    }   
    }

}
============================================

In the above case, the trigger operation will be executed only when the flag value will be false. once the trigger is executed for the first time the flag value is set to true.

NOTE: The flag variable should be a static variable.

Now Some question you can ask about trigger 

Q. Can we call batch apex in the trigger ?
Yes, we can call batch apex from the trigger. But salesforce allows only 5 batch jobs in the queue. So if the trigger raises an error if more than 5 jobs.

Q. Can we call callouts from the trigger ?
We cannot call the callouts directly from the trigger instead, we will define callouts in the future annotated methods and this future annotated methods can be called from the trigger.

NOTE: We can only call 10 callouts in a single transaction.

In this way, we can avoid recursion in the trigger.

In the next Episode, we will discuss Asynchronous Apex. Where we will learn about @future methods.


WOHOOO !! YOU HAVE JUST COMPLETED SALESFORCE RECURSIVE TRIGGER EPISODE

If you like this salesforcekid learning platform please let me know in the Comment section...Also, Share with your salesforce folks wish you 
Happy learning ☁️⚡️ (Learn. Help. Share.)

<< PREVIOUS                                                    NEXT >>

salesforcekid, play store, salesforce number on blog
  

Recursive Triggers In Salesforce Recursive Triggers In Salesforce Reviewed by on Rating: 5

No comments:

HELP !! SHARE !! SUGGEST !!

Powered by Blogger.