Wednesday, March 21, 2018

What is a Recursive Trigger?
A recursive trigger is one that is called over and over, if not controlled will result in this error...
maximum trigger depth exceeded
This is a simple way to create this error via a trigger on an object called Test__c...
trigger TestTrigger on Test__c (before insert) {
    insert new Test__c();
}
With the above trigger in place, when one Test__c object record is created by the user, the trigger executes and then inserts another record of the same type, which causes the trigger to execute again for this record, this keeps repeating until the platform stops things itself. As you can see by this screenshot the platform tolerates up to 8 levels before it stops.
This is what the end user sees eventually...
enter image description here
I have expanded out the error to make it easier to read below...
Review all error messages below to correct your data.
Apex trigger TestTrigger caused an unexpected exception, contact your administrator:
TestTrigger: execution of BeforeInsert caused by: System.DmlException:
Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, TestTrigger: maximum trigger depth exceeded
Test trigger event BeforeInsert for [new] Test trigger event BeforeInsert for [new]
Test trigger event BeforeInsert for [new] Test trigger event BeforeInsert for [new]
Test trigger event BeforeInsert for [new] Test trigger event BeforeInsert for [new]
Test trigger event BeforeInsert for [new] Test trigger event BeforeInsert for [new]
Test trigger event BeforeInsert for [new] Test trigger event BeforeInsert for [new]
Test trigger event BeforeInsert for [new] Test trigger event BeforeInsert for [new]
Test trigger event BeforeInsert for [new] Test trigger event BeforeInsert for [new]
Test trigger event BeforeInsert for [new] Test trigger event BeforeInsert for [new]: []: Trigger.TestTrigger: line 2, column 1
This also applies to other DML operations such as updating or deleting from the same object. Typically you encounter this scenario when you have some kind of hierarchy relationship within your object, such as a parent child and you need to update parent records when child records are effected. There is a good summary in the Context Variables Considerations of what can and cannot be done.
Avoiding Recursive Triggers
The Apex Developers Guide surprisingly does not say much about this, aside from a reference in the Static and Instance topic.
Use static variables to store information that is shared within the confines of the class. All instances of the same class share a single copy of the static variables. For example, all triggers that are spawned by the same transaction can communicate with each other by viewing and updating static variables in a related class. A recursive trigger might use the value of a class variable to determine when to exit the recursion.
Suppose you had the following class:
public class p { 
   public static boolean firstRun = true; 
}
The above example would be adapted to use this approach as follows...
trigger TestTrigger on Test__c (before insert) {
    if(p.firstRun)
    {
        p.firstRun = false;
        insert new Test__c();
    }    
}
Static variables defined in a trigger don’t retain their values between different trigger contexts within the same transaction, for example, between before insert and after insert invocations. Define the static variables in a class instead so that the trigger can access these class member variables and check their static values.
With this approach in place the recursion stops once the trigger is called a second time, as it does not attempt to insert a third record. The result is for every one record a second additional record is created and the recursion is avoided.
Warning: Any form of recursive coding is by definition complicated, as this blog I found illustrates the use of a static flag recording if the trigger has previously been executed can be to simplistic for some use cases, if you don't fully consider your use cases.

--------------------------------------------------------------------------------------------
Recursive trigger in salesforce and how to avoid it?
Recursion occurs when the code gets called again and again and goes into a infinite loop. It is always advisable to write a code that does not call itself. However, sometimes we are left with no choice. Recursion occurs in trigger if your trigger has a same DML statement and the same dml condition is used in trigger firing condition on the same object(on which trigger has been written)
For example, if your trigger fires on after update on contact and you update any contact record in your trigger then the same trigger will be called and will lead to a infinite loop.
To avoid this kind of recursion and call the trigger only once we can use global class static variable.
As an example let says you have following trigger on contact:
?
1
2
3
4
5
6
7
8
9
10
11
trigger recursiveTrigger on Contact (after update) {
Id recordId ;
 for(contact con : trigger.new){
     recordId = con.id;
 }
 Contact conRec =[select id,name,email from contact where id !=: recordId limit 1];
 conRec.email = 'test@test.com';
 update conRec;
 }
}




?
1
2
3
4
5
global Class recusrssionPreventController{
Global static boolean flag = true;
 Public recusrssionPreventController(){
 }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
trigger recursiveTrigger on Contact (after update) {
Id recordId ;
if(recusrssivePreventController.flag == true){
   recusrssivePreventController.flag = false;
 for(contact con : trigger.new){
     recordId = con.id;
 }
 Contact conRec =[select id,name,email from contact where id !=: recordId limit 1];
 conRec.email = 'test@test.com';
 update conRec;
 }
}

What is the  maximum trigger depth exceeded exception in salesforce?

When you are creating an Apex code that recursively fires triggers due to insert/update/delete statement for more than 16 times. You will get the Maximum Trigger Depth Exceeded error.

The following example will demonstrate this issue:

trigger cloneAnotherAcc on Account (before insert) {
Account acc = new Account(name=’Clone me’);
insert acc;
}

This trigger will end up in an infinite loop.

In order for you to solve this issue, you can set a condition on insert so it will not be called recursively. Set a flag to manage the insert trigger will be the ideal. To do this, you need to create a new class to keep track the number of times of insert or stop the insert process on second time.

global class triggerCount {
static integer runTimes = 0;

public static integer getRunTimes(){
return runTimes;
}

public static void setRunTimes(){
runTimes++;
}
}

Once you successfully create this class, you can implement this triggerCount class on your trigger to limit the number of times for insert.

trigger createAcc on Account (before insert) {
if(triggerCount.getRunTimes < 2){
Account acc= new Account(name=’Clone me’);
triggerCount.setRunTimes();
insert acc;
}
}

How to compare old field value with the New field value in Salesforce?


Here you can compare the values with  trigger.oldMap . Here is the sample example on contact email field.

trigger Email_Check_On_Contact on Contact (before update) {
  Map<Id,Contact> o = new Map<Id,Contact>();
    o = trigger.oldMap;
    for(Contact newcont: trigger.new)
    {
      
        if(newcont.Email != o.get(newcont.Id).Email)
        {
            newcont.Email.addError('Email cannot be changed');
        }
    }
}
 How to execute Batch Apex Using Apex Trigger?

Hi,
In this post i am trying to give an example of how to execute Batch Process from Apex Trigger. Here i am calling Batch class from the trigger.

Trigger:

trigger UpdateAreaInfoUser on User (after update)  {
Map<id, User> owners = new Map<id, User>();

for (Integer i=0;i<Trigger.new.size();i++) {
if (Trigger.new[i].Team__c!=Trigger.old[i].Team__c) {
owners.put(Trigger.new[i].Id, Trigger.new[i]);
}
}

// You can execute batch apex using trigger using below codes
if (owners.size() > 0) {
Database.executeBatch(new UpdateAccountArea(owners));
}

}