function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
manish malhothramanish malhothra 

Best ways to avoid recursive trigger

What is a recursive trigger? What are the best ways to avoid recursive triggers can somebody explain with a simple example.Please help me to understand the concept of recursive triggers.

Thanks
Best Answer chosen by manish malhothra
NagendraNagendra (Salesforce Developers) 
Hi Manish,

Please find the below explanation 

What is a Recursive Trigger :
A recursive trigger is one that performs an action, such as an update or insert, which invokes itself owing to,  say something like an update it performs.

How to avoid Recursive Trigger:
To avoid recursive triggers you can create a class with a static Boolean variable with default value true. In the trigger, before executing your code keep a check that the variable is true or not. Once you check make the variable false.

Example:

Apex Code:
public Class checkRecursive{
    private static boolean run = true;
    public static boolean runOnce(){
    if(run){
     run=false;
     return true;
    }else{
        return run;
 }
    }
}

 Trigger Code:
trigger updateTrigger on anyObject(after update) {
    if(checkRecursive.runOnce())
    {
    //write your code here            
    }
}

Example2:


Scenario:
There is an after update trigger on account object. In the trigger, there is a date field we are checking the date is changed or not if it is changed we are doing some process.The trigger is executed five times in the transaction.

Apex Code:
public class ContactTriggerHandler
{
     public static Boolean isFirstTime = true;
}

Trigger Code:
trigger ContactTriggers on Contact (after update)
{
    Set<String> accIdSet = new Set<String>(); 
    if(ContactTriggerHandler.isFirstTime)
    {
        ContactTriggerHandler.isFirstTime = false;
         for(Contact conObj : Trigger.New)
  {
            if(conObj.name != 'Test') 
     {
                accIdSet.add(conObj.accountId);
            }
         }
   // any code here
    }
}
For more information refer to the below link
https://help.salesforce.com/HTViewSolution?id=000199485&language=en_US

Please mark my solution as the best answer if it helps you.

Best Regards,
Nagendra.P

All Answers

Vigneshwaran GurunathanVigneshwaran Gurunathan
I have following business requirement. 

1. When my Account owner is changed, all Opportunities related to that Account should have the same Owner.
2. When my Opportunity owner is changed, the Account with which the Opportunity is related should have the same Owner.

To fulfill my first requirement, I create a trigger in Account(we can do this by Process builder but lets stick to Trigger as we try to understand recursive triggers here) and change the related Opportunties Owner to the currently changed Owner of Account.

To fulfill my second requirement, I create a trigger in Opportunity and change the parent Account Owner to the currencly changed Owner of Opportunity.

Now if you go and change the owner of an Account, the Account trigger gets called and update Opportunity which will call the Opportunity trigger and update Account which in turn call the Account trigger again and goes into loop. Since Salesforce being multi-tenant architecture, Salesforce cannot allow as single org to monopolise the resources and thus stop the loop after 5 executions. This is called recursive triggers.

To avoid this, we need to use Static variables. Static variables retain their value throughout the Transaction. So it will be the same in all the loops. So i have two static variables name isStartOpportunity and isStartAccount with false values.

In Opportunity trigger, I make isStartOpportunity to true and update Account. In Account trigger, i check for isStartOpportunity to be false and update Opportunity.

In Account trigger, I make isStartAccoutn to true and update Opportunity. In Opportunity trigger, i check for isStartAccount to be false and update Account.
 
Account trigger:

if(!avoidRecursive.isStartOpportunity){
	avoidRecursive.isStartAccount = true;
	update Opportunity;
}

Opportunity trigger:

if(!avoidRecursive.isStartAccount){
	avoidRecursive.isStartOpportunity = true;
	update Account;
}

public class avoidRecursive {
	public static boolean isStartAccount = false;
	public static boolean isStartOpportunity = false;
}
Hope it helps to understand better.
 
NagendraNagendra (Salesforce Developers) 
Hi Manish,

Please find the below explanation 

What is a Recursive Trigger :
A recursive trigger is one that performs an action, such as an update or insert, which invokes itself owing to,  say something like an update it performs.

How to avoid Recursive Trigger:
To avoid recursive triggers you can create a class with a static Boolean variable with default value true. In the trigger, before executing your code keep a check that the variable is true or not. Once you check make the variable false.

Example:

Apex Code:
public Class checkRecursive{
    private static boolean run = true;
    public static boolean runOnce(){
    if(run){
     run=false;
     return true;
    }else{
        return run;
 }
    }
}

 Trigger Code:
trigger updateTrigger on anyObject(after update) {
    if(checkRecursive.runOnce())
    {
    //write your code here            
    }
}

Example2:


Scenario:
There is an after update trigger on account object. In the trigger, there is a date field we are checking the date is changed or not if it is changed we are doing some process.The trigger is executed five times in the transaction.

Apex Code:
public class ContactTriggerHandler
{
     public static Boolean isFirstTime = true;
}

Trigger Code:
trigger ContactTriggers on Contact (after update)
{
    Set<String> accIdSet = new Set<String>(); 
    if(ContactTriggerHandler.isFirstTime)
    {
        ContactTriggerHandler.isFirstTime = false;
         for(Contact conObj : Trigger.New)
  {
            if(conObj.name != 'Test') 
     {
                accIdSet.add(conObj.accountId);
            }
         }
   // any code here
    }
}
For more information refer to the below link
https://help.salesforce.com/HTViewSolution?id=000199485&language=en_US

Please mark my solution as the best answer if it helps you.

Best Regards,
Nagendra.P
This was selected as the best answer
Ajinkya DhasAjinkya Dhas
Hi Manish,

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.

For more scenarios and error problems please visit :
https://www.salesforcekid.com/2019/07/recursive-triggers-in-salesforce.html

I hope this will help you to solve your problem.
HAPPY LEARNING ☁️⚡️

AJINKYA DHAS ☁️⚡️
Salesforcekid (http://www.salesforcekid.com)
HarshadaHarshada
Or should we use a Private boolean variable?
raj_sfdccraj_sfdcc
Hi,
Please refer the below Link with explanation and examples .
Recursive Triggers (https://salessforcehacks.blogspot.com/2019/12/salesforce-recursive-triggers-fully.html)
{tushar-sharma}{tushar-sharma}
Hi,
We have multiple ways to avoid recursive triggers. They all depend on your use case, While one solution may work but will not work for others. Check the below links, It has multiple ways to avoid recursive trigger: https://newstechnologystuff.com/2020/05/28/avoid-recursive-trigger-in-salesforce/