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
dawnzdydawnzdy 

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

Message Edited by dawnzdy on 04-15-2009 12:23 PM
Best Answer chosen by Admin (Salesforce Developers) 
WilmerWilmer

Hi

 

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

WilmerWilmer

Hi

 

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

 

This was selected as the best answer
dawnzdydawnzdy

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

Message Edited by dawnzdy on 04-15-2009 03:26 PM
WilmerWilmer

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.

werewolfwerewolf
Incidentally, the limit is still 20 in a trigger.  Perhaps you were running your code in a testMethod, where the limit is increased to 100.
dawnzdydawnzdy

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!

dawnzdydawnzdy

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

Message Edited by dawnzdy on 04-17-2009 08:05 AM
BritishBoyinDCBritishBoyinDC
Thanks Wilmer - I was also baffled by how to get this to work!
WilmerWilmer

Hi ,

 

Try better to work with the change of Probability field instead of stagename to make the trigger be fired.

WilmerWilmer

ok, but do you have any question about or you made it work successfully?

BritishBoyinDCBritishBoyinDC

No question - seems to work fine for me. 

 

Thanks 

Sunil_AroraSunil_Arora

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

nrwingnrwing
Very Nice! Thanks,
ColinKenworthy1ColinKenworthy1

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.

ColinKenworthy1ColinKenworthy1
One thing though that I just noticed. In a test method the boolean does not seem to get reset back to its initial value after an insert, update, etc. So if you are doing several updates on the object in your test method you need to reset the boolean yourself between the updates else you will prevent your trigger code running.
Developer_shaanDeveloper_shaan

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.

WilmerWilmer

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

Eric KintzerEric Kintzer
The static variable solution will not work if the trigger is invoked when AllOrNone header = false (Data Loader for example) and one or more records in the batch fail. This is because SFDC will (rollback any updates from the successes), and retry the records in the batch that succeeded. But the static variable is not reset in the retry and your trigger will then end up doing nothing and your database will be inconsistent.