9

While going through apex pdf i got line

Static variables defined in a trigger don’t retain their values between different trigger contexts".

Can anyone please explain me with some code sample. I am confused as to what is the meaning of defining a static variable inside a trigger. Static variables are are used in Class context. So what a static variable does in trigger context.

3 Answers 3

12

The following code is valid for a trigger:

trigger countInvocations on Contact (after insert, after update) {
    static Integer count;
    if(count == null) {
        count = 0;
    }
    count++;
}

However, this will lead to some unexpected results if you attempt to use recursive contexts (e.g. performing an update after insert), or multiple updates (e.g. from a controller). The variable in the example above will always be null initially upon entering trigger context, despite being a static variable. Line 4 will always execute, and Line 6 will always set the value to 1. To have static values persist across triggers, one has to put the static variables within a class.

6
  • This is my trigger code and I am inserting record in contact using contact tab on salesforce UI. trigger t2 on Contact (Before insert) { static Boolean b = true; if(b==true) { System.debug('-------- Inside triggers if') b=false; } System.debug('-----outside if'); } Here I am getting two debug statement everytime a record is inserted. This is not any recursive case then how come I am getting two debug statement Jan 5, 2015 at 8:57
  • 1
    Most likely a workflow rule with a field update is causing this. Try disabling your workflow rules.
    – sfdcfox
    Jan 5, 2015 at 16:34
  • I haven't defined any workflow rule! Jan 6, 2015 at 5:27
  • @MonalisaDas I'd have to have a look at your log files. Do you think you could send me a sample log file where you're observing a trigger firing twice for no apparent reason?
    – sfdcfox
    Jan 8, 2015 at 18:19
  • You can find the log files in this link docs.google.com/document/d/… Jan 9, 2015 at 9:00
8

A static variable retains it`s value throughout an execution context. An execution context is invoked from a button click, web service call, a trigger etc.

One of the many ways a static variable can be used is to flag when a trigger has already fired and what to do with a re-entrant trigger.

Suppose you had the following class:

public class p { 
   public static boolean firstRun = true; 
} 

A trigger that uses this class could then selectively fail the first run of the trigger:

trigger t1 on Account (before delete, after delete, after undelete) { 
       if(Trigger.isBefore){
          if(Trigger.isDelete){
             if(p.firstRun){
                 Trigger.old[0].addError('Before Account Delete Error');
                  p.firstRun=false;
              } 
           }
        }
}

If the static variable was set in the trigger like this:

trigger t1 on Account (before delete, after delete, after undelete) { 
       static boolean firstRun = true; 

       if(Trigger.isBefore){
          if(Trigger.isDelete){
             if(p.firstRun){
                 Trigger.old[0].addError('Before Account Delete Error');
                  p.firstRun=false;
              } 
           }
        }
}

When the trigger might fire again on the same object, even if you set it to false in the next trigger context it will still be set to true and code will execute something that was not planned.

From what I found the Apex runtime engine considers, an operation of a trigger, a single unit of work so it might be that when the second time a trigger executes the engine focuses on the particular trigger and not the previous one. So by putting the static variable in a class, it`s life is governed by the whole execution context which might be composed of many actions and not the trigger execution context.

UPDATE

I've been reading about static variables in trigger and there are a couple of reasons why you should not use them:

  1. It is bad practice to write logic inside your trigger, minimizing the amount of code in a trigger and instead implement all functionality in class.
  2. Having static variables separated in a class will help you with the unit test by loading up the static variables with the required data and not rely on the fact that you have to trigger the trigger in order to populate with test data test your scenario.
  3. Also the most important thing to know about triggers is that when you have more than one trigger of the same type, you cannot predict the order in which they will fire. So if you have a static variable in a trigger that has a value that another trigger will depend on than you would have some problems.

Hope it helps, if you think some code will help you to understand better, let me know.

2
  • So if we want to use something like static in trigger context we have to opt for static variable of apex class.Than in that case what a static variable do in trigger context.My question is still the same what is the meaning of declaring static and non static variable inside trigger.Instance variable inside a class is associated with instance of that class so instance member inside a trigger is associated with instance of what ? Jan 5, 2015 at 8:10
  • Updated my answer Jan 8, 2015 at 11:15
2

Sorry for hijacking the thread, but I recently had a somewhat interesting idea on handling recursion, perhaps someone will comment on this. Working on larger projects you might want to have fine grained control of recursion. Some objects should never recur, some - at particular context (after update) or even at certain methods.

What you could end up with is a ton of static variables that will eventually become hard to maintain and new developers might just start creating new ones. So instead, why not use one map of booleans (or integers if you wish to control how many recursions to execute)?

This way, you'd just have this in your utility method:

public static map <string, boolean> recursion = new map <string, boolean>();

And before each DML you do :

util.recursion.put('Contacts.BeforeInsert.UpdateParents'), true)
update lstContacts;

And place this in the beginning of your method

if ( util.recursion.get('Accounts.afterUpdate.callBambi') ) return;

What do you guys think?

1
  • It a good idea. Makes it easy to work with dynamic object names for managed packages. Oct 2, 2020 at 5:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .