+ Start a Discussion
Andrew DiBaccoAndrew DiBacco 

Infinitie loop with two triggers

Hi everyone,

I have a requirement that needs me to link a user id field on a custom object to another user id field on the opportunity object. When the id field is updated from either object, I want the corresponding field on the other object to update with the same user. The custom and opportunity objects are connected to each other by two lookup relationship fields. (Implementation__c on the Opportunity and Opportunity__c on the custom object)  These are the two triggers I wrote:

1 trigger UpdateESS on Opportunity (after insert, after update) {
2
3      List<ID> ImpIds = New List<ID>();
4
5       for(Opportunity o : Trigger.new){
6       if(o.Assigned_trainer__c != null && o.Implementation__r.Education_Support_Specialist__c  == null){
7           ImpIds.add(o.Implementation__c); 
8       } 
9   }
10     
11   
12  List<Implementation__c> ImpList = [SELECT id, Education_Support_Specialist__c, opportunity__c FROM Implementation__C WHERE id in :ImpIds];
13   
14   Map<id,Opportunity> mImptoOpp = New Map<id,Opportunity>();
15       for(Opportunity k : trigger.new){
16           if(k.Assigned_Trainer__c != null && k.Implementation__r.Education_Support_Specialist__c == null){ 
17               mImptoOpp.put(k.implementation__c, k);              
18           }
19       }    
20  for(integer i = 0 ; i < ImpList.size(); i++){ 
21    ImpList[i].Education_Support_Specialist__c = mImptoOpp.get(ImpList[i].id).Assigned_Trainer__c;
22    }        
23 Update ImpList;
24 }

1 trigger UpdateAssignedTrainer on Implementation__c (after insert, after update) {
2
3   List<ID> OppIds = New List<ID>();
4
5   for(Implementation__c o : Trigger.new){
6       if(o.Education_Support_Specialist__c != null && o.Opportunity__r.Assigned_Trainer__c == null){
7           OppIds.add(o.Opportunity__c);  
8       } 
9   }  
10   
11   List<Opportunity> OppList = [SELECT id, Assigned_Trainer__c, implementation__c FROM Opportunity WHERE id in :OppIds];
12   
13   Map<id,Implementation__c> mImptoOpp = New Map<id,Implementation__c>();
14       for(Implementation__c k : trigger.new){
15           if(k.Education_Support_Specialist__c != null && k.Opportunity__r.Assigned_Trainer__c  == null){ 
16               mImptoOpp.put(k.Opportunity__c, k);
17           }
18       } 
19   
20 for(integer i = 0 ; i < OppList.size(); i++){ 
21    OppList[i].Assigned_Trainer__c = mImptoOpp.get(OppList[i].id).Education_Support_Specialist__c; 
22    } 
23 Update OppList;  
24 }

The two triggers are essentially identical, except they are initiated by and update the opposite object. The issue I'm having (at least I think this is what's happening) is that the DML statement that saves the changes to the database actually causes the other trigger to fire, creating the infinite loop.  I tried adding conditions to the trigger that would prevent the loop, but I think the trigger executes before the new data value can be comitted to the database. Is it possible to stop the DML statement from firing the second trigger? Could combining these triggers resolve the issue? Any advice would be much appreciated.

Here's the actual error in case I am misunderstanding what is happening:

Error:Apex trigger UpdateESS caused an unexpected exception, contact your administrator: UpdateESS: execution of AfterUpdate caused by: System.DmlException: Update failed. First exception on row 0 with id a0BW000000JNK7aMAH; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, UpdateAssignedTrainer: maximum trigger depth exceeded Opportunity trigger event AfterUpdate for [006W000000605S1] Implementation trigger event AfterUpdate for [a0BW000000JNK7a] Opportunity trigger event AfterUpdate for [006W000000605S1] Implementation trigger event AfterUpdate for [a0BW000000JNK7a] Opportunity trigger event AfterUpdate for [006W000000605S1] Implementation trigger event AfterUpdate for [a0BW000000JNK7a] Opportunity trigger event AfterUpdate for [006W000000605S1] Implementation trigger event AfterUpdate for [a0BW000000JNK7a] Opportunity trigger event AfterUpdate for [006W000000605S1] Implementation trigger event AfterUpdate for [a0BW000000JNK7a] Opportunity trigger event AfterUpdate for [006W000000605S1] Implementation trigger event AfterUpdate for [a0BW000000JNK7a] Opportunity trigger event AfterUpdate for [006W000000605S1] Implementation trigger event AfterUpdate for [a0BW000000JNK7a] Opportunity trigger event AfterUpdate for [006W000000605S1] Implementation trigger event AfterUpdate for [a0BW000000JNK7a]: []: Trigger.UpdateESS: line 23, column 1
Best Answer chosen by Andrew DiBacco
Mohan_ShanmugamMohan_Shanmugam
Hi Andrew,

Its a recursive trigger and it has to be controlled by a Static variable.

Write a simple class like below.
public class RecursiveTriggerHandler{
     public static Boolean isTriggered = true;
}
and in "both" the trigger use the below condition and replace "//Your Functionality" by your functionality.
 
if(RecursiveTriggerHandler.isTriggered ){
        RecursiveTriggerHandler.isTriggered = false;

        //Your Functionality

}

its should work!!

Thanks,
Mohan Shanmugam

 

All Answers

Mohan_ShanmugamMohan_Shanmugam
Hi Andrew,

Its a recursive trigger and it has to be controlled by a Static variable.

Write a simple class like below.
public class RecursiveTriggerHandler{
     public static Boolean isTriggered = true;
}
and in "both" the trigger use the below condition and replace "//Your Functionality" by your functionality.
 
if(RecursiveTriggerHandler.isTriggered ){
        RecursiveTriggerHandler.isTriggered = false;

        //Your Functionality

}

its should work!!

Thanks,
Mohan Shanmugam

 
This was selected as the best answer
Anil KamisettyAnil Kamisetty
Yes, you should make use of Static Variable, others are not helpful here. You have to define the Static Variable in a Seperate Class (outside of these triggers) and switch the value in these triggers. You will Process / Skip the trigger alltogether based on Static Variable Value.
Andrew DiBaccoAndrew DiBacco
Thanks Mohan and Anil! I added the static variable and now my triggers work the way they are supposed to.