You need to sign in to do that
Don't have an account?
ChickenOrBeef
Recursion check prevents After triggers from running
Greetings everyone,
I recently changed all my triggers to classes and then created a main trigger for each object that calls the classes for each respective object.
Anywho, my opportunity trigger calls quite a few classes. The issue is that if I don't add a recursion check, I can't deploy the trigger due to the SOQL query limit being broken. But if I do add the recursion check, only the Before triggers work. Not the After triggers.
Here is the trigger (with the recursion call up top):
trigger MainTriggerOpportunity on Opportunity (before insert, before update, after insert, after update) {
if(checkRecursive.runOnce()){
if(trigger.isBefore){
if(trigger.isInsert){
ClassOppIndustry updater = new ClassOppIndustry();
updater.updateOppIndustry(trigger.new);
ClassRenewalDate updater1 = new ClassRenewalDate();
updater1.updateRenewalDate(trigger.new);
}
if(trigger.isUpdate){
ClassOppIndustry updater = new ClassOppIndustry();
updater.updateOppIndustry(trigger.new);
ClassRenewalDate updater1 = new ClassRenewalDate();
updater1.updateRenewalDate(trigger.new);
}
}
if(trigger.isAfter){
if(trigger.isInsert){
ClassRenewalProcess updater = new ClassRenewalProcess();
updater.updateRenewalStatus(Trigger.new);
ClassOppBrandCreate updater1 = new ClassOppBrandCreate();
updater1.addBrand(trigger.new);
}
if(trigger.isUpdate){
ClassRenewalProcess updater = new ClassRenewalProcess();
updater.updateRenewalStatus(Trigger.new);
ClassOppBrandCreate updater1 = new ClassOppBrandCreate();
updater1.addBrand(trigger.new);
ClassChatterAlerts updater2 = new ClassChatterAlerts();
updater2.addChatterAlert(Trigger.new,Trigger.oldMap);
}
}
}
}
Here is the recursion check class:
public Class checkRecursive{
private static boolean run = true;
public static boolean runOnce(){
if(run){
run=false;
return true;
}
else{
return run;
}
}
}
Perhaps I have to allow the trigger to run twice? I'm a newb, so any help would be much appreciated!
Thanks,
Greg
I recently changed all my triggers to classes and then created a main trigger for each object that calls the classes for each respective object.
Anywho, my opportunity trigger calls quite a few classes. The issue is that if I don't add a recursion check, I can't deploy the trigger due to the SOQL query limit being broken. But if I do add the recursion check, only the Before triggers work. Not the After triggers.
Here is the trigger (with the recursion call up top):
trigger MainTriggerOpportunity on Opportunity (before insert, before update, after insert, after update) {
if(checkRecursive.runOnce()){
if(trigger.isBefore){
if(trigger.isInsert){
ClassOppIndustry updater = new ClassOppIndustry();
updater.updateOppIndustry(trigger.new);
ClassRenewalDate updater1 = new ClassRenewalDate();
updater1.updateRenewalDate(trigger.new);
}
if(trigger.isUpdate){
ClassOppIndustry updater = new ClassOppIndustry();
updater.updateOppIndustry(trigger.new);
ClassRenewalDate updater1 = new ClassRenewalDate();
updater1.updateRenewalDate(trigger.new);
}
}
if(trigger.isAfter){
if(trigger.isInsert){
ClassRenewalProcess updater = new ClassRenewalProcess();
updater.updateRenewalStatus(Trigger.new);
ClassOppBrandCreate updater1 = new ClassOppBrandCreate();
updater1.addBrand(trigger.new);
}
if(trigger.isUpdate){
ClassRenewalProcess updater = new ClassRenewalProcess();
updater.updateRenewalStatus(Trigger.new);
ClassOppBrandCreate updater1 = new ClassOppBrandCreate();
updater1.addBrand(trigger.new);
ClassChatterAlerts updater2 = new ClassChatterAlerts();
updater2.addChatterAlert(Trigger.new,Trigger.oldMap);
}
}
}
}
Here is the recursion check class:
public Class checkRecursive{
private static boolean run = true;
public static boolean runOnce(){
if(run){
run=false;
return true;
}
else{
return run;
}
}
}
Perhaps I have to allow the trigger to run twice? I'm a newb, so any help would be much appreciated!
Thanks,
Greg
Try the following changes.
trigger MainTriggerOpportunity on Opportunity (before insert, before update, after insert, after update) {
//
if(checkRecursive.runOnce()){if(trigger.isBefore){
if(checkRecursive.runBeforeOnce()){
if(trigger.isInsert){
ClassOppIndustry updater = new ClassOppIndustry();
updater.updateOppIndustry(trigger.new);
ClassRenewalDate updater1 = new ClassRenewalDate();
updater1.updateRenewalDate(trigger.new);
}
if(trigger.isUpdate){
ClassOppIndustry updater = new ClassOppIndustry();
updater.updateOppIndustry(trigger.new);
ClassRenewalDate updater1 = new ClassRenewalDate();
updater1.updateRenewalDate(trigger.new);
}
}// End of IF added
}
if(trigger.isAfter){
if(checkRecursive.runAfterOnce()){
if(trigger.isInsert){
ClassRenewalProcess updater = new ClassRenewalProcess();
updater.updateRenewalStatus(Trigger.new);
ClassOppBrandCreate updater1 = new ClassOppBrandCreate();
updater1.addBrand(trigger.new);
}
if(trigger.isUpdate){
ClassRenewalProcess updater = new ClassRenewalProcess();
updater.updateRenewalStatus(Trigger.new);
ClassOppBrandCreate updater1 = new ClassOppBrandCreate();
updater1.addBrand(trigger.new);
ClassChatterAlerts updater2 = new ClassChatterAlerts();
updater2.addChatterAlert(Trigger.new,Trigger.oldMap);
}
}// End of IF added
}
}
Here is the recursion check class:
public Class checkRecursive{
private static boolean runbefore = true;
private static boolean runafter = true;
public static boolean runBeforeOnce(){
if(runbefore){
runbefore=false;
return true;
}
else{
return runbefore;
}
}
public static boolean runAfterOnce(){
if(runafter){
runafter=false;
return true;
}
else{
return runafter;
}
}
}
-----
Thank you
Choose it as Best Answer if it resolved your issue.
I have a BEFORE trigger on Opportunities that contains a SOQL query, and I also have an AFTER trigger on Opportunities that updates another Opportunitiy. I believe that causes the recursion. I actually made a thread on here before about those two triggers, and then someone pointed me towards the recursion check class I used.
Here is the thread: https://developer.salesforce.com/forums/ForumsMain?id=906F00000009HzbIAE
@Chidambar
I made the changes and the trigger seems to work, but now I'm trying to get 100% code coverage on the main trigger. I can only get up to 61% now, while I was able to get 100% without the new recursion check you made.
I'm not sure how testing works once you only use one main trigger that references classes. Do I just need to make a test class that inserts and updates an opportunity? Or do I need to test the code in all the classes as well? Does this recursion check change things?
Thanks for the help so far, but any further guidance would be much appreciated!
Thanks,
Greg
@isTest
public class testChatterAlerts{
static testMethod void testChatter() {
Account tAccount = new Account();
tAccount.Name = 'Coca Cola';
tAccount.Region__c = 'Canada';
tAccount.Industry = 'Sports';
tAccount.Status__c = 'Prospect';
tAccount.Website = 'www.cocacola.com';
tAccount.FB_Page_1_Fans__c = 30000;
tAccount.FB_Page_1_Link__c = 'www.facebook.com/cocacola';
tAccount.BillingState = 'NY';
tAccount.Most_Recent_Subscription__c = 'Annual';
INSERT tAccount;
Account tBrand = new Account();
tBrand.Name = 'Cherry Coke';
tBrand.Region__c = 'APAC';
tBrand.Industry = 'Restaurants';
tBrand.Status__c = 'Prospect';
tBrand.Website = 'www.cherrycoke.com';
tBrand.FB_Page_1_Fans__c = 10500;
tBrand.FB_Page_1_Link__c = 'www.facebook.com/cherrycoke';
tBrand.BillingState = 'CT';
tBrand.Most_Recent_Subscription__c = 'Fixed Term';
INSERT tBrand;
Contact tContact = new Contact();
tContact.FirstName = 'Bob';
tContact.LastName = 'Barker';
tContact.AccountId = tAccount.Id;
INSERT tContact;
Opportunity tOppty = new Opportunity();
tOppty.Name = 'Coka Annual';
tOppty.StageName = 'Active Discussions';
tOppty.AccountId = tAccount.Id;
tOppty.Brand__c = tBrand.Id;
tOppty.Lead_Origin__c = 'Inbound Lead';
tOppty.Primary_Contact__c = tContact.Id;
tOppty.CloseDate = date.parse('3/15/14');
tOppty.Effective_Date__c = date.parse('3/18/14');
tOppty.Term__c = 5;
INSERT tOppty;
Opportunity rOppty = new Opportunity();
rOppty.Name = 'Coka Renewal';
rOppty.StageName = 'Call Held';
rOppty.AccountId = tAccount.Id;
rOppty.Renewed_Opportunity__c = tOppty.Id;
rOppty.Lead_Origin__c = 'Inbound Lead';
rOppty.Primary_Contact__c = tContact.Id;
rOppty.CloseDate = date.parse('9/15/14');
INSERT rOppty;
rOppty.StageName = 'Negotiations';
rOppty.Brand__c = tBrand.Id;
rOppty.Effective_Date__c = date.parse('10/18/14');
rOppty.Term__c = 7;
UPDATE rOppty;
}
}
http://salesforce.stackexchange.com/questions/16322/trigger-isexecuting-clarification
I know this an old post, but what was the solution for this?
Thanks!
In my original post I had one recursion check for the entire trigger. The solution was to have a separate recursion check for each instance of Before/Insert, Before/Update, After/Insert, After/Update, etc.
For example, my Account trigger looks like this:
And my recursion check class for the Account trigger looks like this:
-Greg
So, my biggest problem with this pattern is.... There's a single class for a recursion check??? You've got to be kidding me if you're going to A) Call a class "recursionCheck" (and I'm not just talking about lowerCamelCasing it), but B) think that you're only going to have a single occurrence of this in your entire org.
Optimally, you would want to have one or more Boolean static variables on your trigger handlers for each use case.
Example:
Remember, making something static only persists for the execution context, which is almost always what you're looking to keep track of in a recursive trigger scenario. Please, no more checkRecursive!!