You need to sign in to do that
Don't have an account?

Trigger is fired twice due to the workflow rule field update
Hi,
I have a trigger on opportunity update which will update the opportunity line items accordingly.
Through the debug log I found the trigger is triggered twice, even though I specify it will only be triggered if there is a stage change from sA to sB.
From the discussion board, I found the reason is due to certain workflow rule did field update right after the trigger. But the funny thing is after the first firing, the previous stage of the opportunity is still considered as sA instead of sB, while the opportunity line items data did accumulated after the firing.
In the end, the number of line items doubled. Although I have ways to prevent the line items from the second round of accumulation, I am just curious how to deal with the second fire of trigger?
Btw, I found the governer limit of SOQL in sandbox increased from 20 to 100! Good news!
Thanks,
Dawn
Hi dawnzdy,
One workaround is to set a private static variable in a global class so it works as a flag, not avoiding the trigger fires twice instead it avoids overpassing the limits.
Something like this. Create a Validator Class:
global class Validator_cls{ private static boolean blnAlreadyDone = false; public static boolean hasAlreadyDone(){ return blnAlreadyDone; }
public static void setAlreadyDone() {
blnAlreadyDone = true;
} }
In the trigger include a line like this one:
trigger OpportunityTrigger_tgr on Opportunity (before insert, before update) { if(!Validator_cls.hasAlreadyDone()){ // Your trigger code here Validator_cls.setAlreadyDone(); } }
So, when the trigger is fired by the first time it sets the flag in true and at the second time it won't pass again over the executed code.
I hope this helps.
Regards,
Wilmer
All Answers
Hi dawnzdy,
One workaround is to set a private static variable in a global class so it works as a flag, not avoiding the trigger fires twice instead it avoids overpassing the limits.
Something like this. Create a Validator Class:
global class Validator_cls{ private static boolean blnAlreadyDone = false; public static boolean hasAlreadyDone(){ return blnAlreadyDone; }
public static void setAlreadyDone() {
blnAlreadyDone = true;
} }
In the trigger include a line like this one:
trigger OpportunityTrigger_tgr on Opportunity (before insert, before update) { if(!Validator_cls.hasAlreadyDone()){ // Your trigger code here Validator_cls.setAlreadyDone(); } }
So, when the trigger is fired by the first time it sets the flag in true and at the second time it won't pass again over the executed code.
I hope this helps.
Regards,
Wilmer
Wilmer,
Thanks very much for your help.
I have tried this. But this means the trigger will only work once, the first time it's fired.
If I change the stage of the same opportunity back and forth or update a different opportunity later, it won't be triggered at all.
How to solve this or did I miss anything?
Thanks a lot!
Dawn
Hi,
well, with this workaround the trigger is fired twice but it will only work once, avoiding limits. Later, if there is another update on the same record, it will work again with no problem. I have tried it before and it works fine.
The flag blnAlreadyDone value will be false everytime an user updates an Opportunity record and saves it, becomes true only by the trigger and after the trigger ends it returns to false automatically.
Also, there is not problem if different users are working simultaneosly, the flag keeps a separated value for each user.
Try it again. It works.
Wilmer, it worked!
Thanks so much! I made a stupid mistake before.
For werewolf
That limit came back to 20 today. I didn't run in testMethod,but a real interaction. One day free trial!
Thanks for your answer!
I like this board a lot!
Hi Wilmer,
Thanks very much for your reply.
Just one more thing, I tried to adopt this for other two existing triggers(update/insert). And the test running turns out to be failure.
In the test method, I insert a opty and update it's stage to satisfy the trigger's criteria (the trigger is to create a case for purchased opty). In this case, the trigger should be fired twice.One after the insert and one after the update action.
However, no case was created after the update action as I expected.
Not sure why, is this because the global var is set to true after the first firing?
When will the global variable will be set back to false? After each DML action?
Thanks!
Dawn
Hi dawnzdy,
Try better to work with the change of Probability field instead of stagename to make the trigger be fired.
ok, but do you have any question about or you made it work successfully?
No question - seems to work fine for me.
Thanks
Hi,
I tried this, and it works fine,
However, It is working only for 100 records, if we use bulk insert/update. Please let me know, if you have any idea to use it for more than 100 records.
Thanks,
Sunil
Like a few people here my initial thoughts were the boolean value (being a static) would remain set until the user logged out. However I can edit the stage up and down and back again and each time the boolean is back to its initial value (ready to stop the trigger code running twice in the one transaction). Also, as said previously, each user has their own independant copy of the boolean.
This is a great (simple) pattern that has sorted out a big headache for me :-)
THANKS.
Hey Wilmer,
Your post is exactly working if we want to avoid the trigger from a class based on a global variable.
But it is not working when used the system.schedule method in a class.
To be more clear, i have implemented the scheduling feature which calls a class daily at 12 AM . The function of job is that some calculation is being done when clicked on save button. But for this there is another trigger written which fires when the records are being updated. I need to avoid the trigger being fired and allow the normal manual calculation from class.
I tried passing a global variable in the class that is being called in system.schedule method.
But the trigger is being fired how to avoid the trigger.??
Please let me know if any soln.
Hi Shaan,
I'm afraid this couldn't be a solution when it is used in schedule or future method, because the class you call to, runs in different execution context.
Perhaps, a workaround, could be to use a hidden checkbox field in order to mark the record, process it with the future (or schedule) method and avoid the second trigger activity.
I hope this helps.
Regards,
Wilmer