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
tonantetonante 

Question Regarding KB 000199485 - Trigger Recursion

HI I just needed clarification on this solution that I made to the KB and wondered if I am understanding the action involved (semaphore?).
Before using the code in this solution I would have trigger recursion where one trigger process called a multiple number of times when it fired,  For example: trigger  Registration(  which fires when  Account is being inserted or before the acocunt is updated) would fire 10 times when Contact After Update trigger is fired once but there are 4 other triggers (i don;t have all their file names)  that fire only once.  This wastes time and uses unwanted resources. When I used the KB solution 000199485  above I noticed,  while looking at the debug log system.debug statements,  that the Registration trigger fires only once  (which is good) but the other 4 triggers don't get to run. To solve this , I set the static boolean flag -  firstRun - to true after the Trigger's IF Conditional  has been executed by making a call to isResetRun() method. Therefore when I re-fire the Contact After Update trigger , all the trigger processes fire once per trigger and no more because they got permission when the
firstRun flag was reset to true otherwise the other triggers would still see the flag as false and quickly exit.

Q) Is this the correct/intended result?  Here is a code sample of what I meant and pay special attention to the
checkRecursive.isResetRun() method call which I added to the KB solution code:
 
trigger AccountAfterUpdate on Account (after update) {  
if(checkRecursive.isFirstRun()){	// To avoid the recursion on trigger One Trigger Per Object
    Integer acctLimit = Trigger.new.size();             
    List<Account> UpdateAccountList = new List<Account>();     
    List<Account> UpdateRegLevelList = new List<Account>();     
    List<ID> acctIDs = new List<ID>();
    List<Account> clonedAccounts = new List<Account>();
    Account modifiedAccount;
    Account clonedAccount;
    List<RecordType> getPersonRecordType = [Select Id from recordType where Name = 'Individual_Person'];
    List<RecordType> getUSRecordType = [Select Id from recordType where Name = 'US Organization'];
    List<Account> OtherAccounts = new List<Account>();  //non-PMM Account tasks. 
	//1. See if its PMM value has changed for Account records.
    for(Integer aCnt = 0; aCnt < acctLimit; aCnt++){
    	//A. <<For Address Synchronization:>> // See if Address have been updated for Person Accounts
    	if(Trigger.new[aCnt].RecordTypeId == getPersonRecordType[0].Id){
            if(Trigger.new[aCnt].ShippingStreet != Trigger.old[aCnt].ShippingStreet ||
                Trigger.new[aCnt].ShippingCity != Trigger.old[aCnt].ShippingCity ||
                Trigger.new[aCnt].ShippingState != Trigger.old[aCnt].ShippingState ||
                Trigger.new[aCnt].ShippingCountry != Trigger.old[aCnt].ShippingCountry ||
                Trigger.new[aCnt].ShippingPostalCode != Trigger.old[aCnt].ShippingPostalCode ||
                Trigger.new[aCnt].BillingStreet != Trigger.old[aCnt].BillingStreet ||
                Trigger.new[aCnt].BillingCity != Trigger.old[aCnt].BillingCity ||
                Trigger.new[aCnt].BillingState != Trigger.old[aCnt].BillingState ||
                Trigger.new[aCnt].BillingCountry != Trigger.old[aCnt].BillingCountry ||
                Trigger.new[aCnt].BillingPostalCode != Trigger.old[aCnt].BillingPostalCode
                ){                    
			modifiedAccount = Trigger.new[aCnt];
                    	clonedAccount = new Account(Id=modifiedAccount.Id, Physical_Street_1__c =modifiedAccount.BillingStreet, Physical_City__c = modifiedAccount.BillingCity,
                                                Physical_Zip__c = modifiedAccount.BillingPostalCode,Physical_State__c = modifiedAccount.BillingState,
                                                PhysicalCountry__c = modifiedAccount.BillingCountry,Mailing_Street_1__c = modifiedAccount.ShippingStreet,
                                                Mailing_City__c = modifiedAccount.ShippingCity,Mailing_State_Province__c = modifiedAccount.ShippingState,
                                               Mailing_Zip_Postal_Code__c = modifiedAccount.ShippingPostalCode,Mailing_Country__c = modifiedAccount.ShippingCountry);
            
                    clonedAccounts.add(clonedAccount);
               }
          }  

        //B.<<For Team Member Manager:>> Check to see if the Owner Id has changed on US Organizations
       if(Trigger.new[aCnt].RecordTypeId == getUSRecordType[0].Id){ //11-23-2014 Added conditional using Record Type as a flag to process for US Orgs only.
        	if(Trigger.new[aCnt].OwnerId != Trigger.old[aCnt].OwnerId && (Trigger.new[aCnt].OwnerId != null && Trigger.old[aCnt].OwnerId != null) ){ // This should never happen  for Person Accounts.
          		UpdateAccountList.add(Trigger.new[aCnt]);
            	acctIDs.add(Trigger.new[aCnt].Id);
                
       		 }//IF
       }//IF
      
    }// FOR
	//2. <<For Team Member Manager:>> Displatch for processing which accounts ..
    if(UpdateAccountList.size() > 0){
        system.debug('<<TMACCTS>> '+UpdateAccountList);
        TeamMemberAccounts.handler(UpdateAccountList,acctIDs);       
    }  
  //3. <<For Address Synchronization on Person Accounts:>>
     if(clonedAccounts.size() > 0 ){
     	  update clonedAccounts;
     	  system.debug('*** New ACCOUNT ID *** '+clonedAccounts[0].Id+' *** New ACCOUNT Mailingn Address *** '+clonedAccounts[0].Mailing_Street_1__c+' *** New ACCOUNT PhysicalAddress *** '+clonedAccounts[0].Physical_Street_1__c); 
     	             
     }   
        
}// checkRecursion  
// Before leaving, give 'key' to the next available trigger to unlock critical section for  Access.

checkRecursive.isResetRun();  // <------------ KB Class Update. Free up the firstRun'key' .
}

The Class Code for the Semaphore used in the KM solution I changed slightly by adding a method called
isResetRun:
public class checkRecursive{
	
	private static boolean firstRun = true;
    public static boolean isFirstRun(){
    	if(firstRun){
      		firstRun = false;
      		return true;
    	}else{
        	return firstRun;
    	}
    }
    public static boolean isResetRun(){ // <------------ New method to free up the 'key' firstRun
    	firstRun = true;
    	return true;
    }
}// checkRecursive

Thanks for your help, comments, and questions. I just want to make sure that either I fixed the KB or if I have accidentally created any additional problems for myself . Again, with my solution  the 4 trigger processes only fire once after a contact has been updated.
 
 
KaranrajKaranraj
By reseting the variable at the end of the your code it will allow the trigger to execute one more time, if there is any workflow or trigger performs update on the account in the same execution context. If you really want to execute the trigger only once in the exection context you don't need to reset the value again at the end of the code.

Note: - The static variable will hold the value only in that execution context, after that it will automatically reset to the initally value as true.
tonantetonante
karanraj, OK I will test your solution to make sure but I thought that when I removed the reset that no other triggers ran which means that I only have the Registration trigger running but the AccountGeoCodeAfterUpdate will not run at all. (I saw this happn within the log file.)