1

I want a before update trigger to remember which of the objects need something done in the after trigger handler. I tried this but I get a null reference:

public class OpportunityTriggerHandler {
...
private Set<Id> idsToRecompute;

public void OnBeforeUpdate(Opportunity[] oldEntries, Opportunity[] updatedEntries, Map<ID, Opportunity> oldMap) {
  idsToRecompute = new Set<Id>();  // this will be used in AfterUpdate
  //  based on data, set recomputeIds to a subset of the op ids
  ...
public void OnAfterUpdate(Opportunity[] oldItems, Opportunity[] newItems, Map<ID, Opportunity> oldMap) {
  ... D'oh! idsToRecompute is null now!

Can anyone suggest a way to implement this strategy?

2 Answers 2

6

If you mark your variable as static it will persist between before and after triggers, but only if you leave the variable in a class (if you have a static variable in the actual trigger, it will not persist across invocations). So, your code would look like:

public class OpportunityTriggerHandler {
private static Set<Id> idsToRecompute;

public void OnBeforeUpdate(Opportunity[] oldEntries, Opportunity[] updatedEntries, Map<ID, Opportunity> oldMap) {
  idsToRecompute = new Set<Id>();
}
public void OnAfterUpdate(Opportunity[] oldItems, Opportunity[] newItems, Map<ID, Opportunity> oldMap) {
    for(ID i: idsToRecompute){
        System.debug(i);
    }
}
6
  • The above would only work if you're using a trigger platform where there's an instance of an external class that would hold the static variable that persisted across both contexts in the execution context (like a trigger handler instance helper that used a static singleton pattern). Otherwise, any additional instantiations of the same class that ran concurrently would interfere with one another.
    – crmprogdev
    Commented Jun 18, 2017 at 16:03
  • @crmprogdev: The answer has an example of the class that will hold the static variable. If this handler class is instantiated multiple times, there will still only be one OpportunityTriggerHandler.idsToRecompute value, since it is marked as static. There shouldn't be any interference. Commented Jun 18, 2017 at 16:27
  • @JeremyNottingham The instantiations would interfere with each other. I don't feel like it's worth pointing out in the answer though, since that's a property of static variables and doesn't have anything to do with the Trigger context. I also have trouble imagining a TriggerHandler implementation that's anything other than a singleton. On the other hand, if you had multiple trigger handlers extending one TriggerHandler class, and the parent class had the static variable, I think that is shared between all children, though honestly I don't remember. Commented Jun 18, 2017 at 17:26
  • @JeremyNottingham If the class is instantiated, it would interfere with another class of the same name instantiated and running at the same time. In the case of an instance, it would not. However, depending on how the instance class is called from an instance of a "trigger main" class, an instance handler class might be instanced twice (once for each context); making this pattern unusable. An instance of "trigger main" would definitely need to be the place to hold the static variable to prevent issues as is done in Appleman's Trigger pattern.
    – crmprogdev
    Commented Jun 18, 2017 at 21:41
  • @crmprogdev If you do need to instantiate multiple instances of the class, you can store instances of the class in a static collection variable and keep the data needed per class internal to the class instance. That seems unnecessary for the use case presented though. Commented Jun 18, 2017 at 22:07
0

I found a way to do this:

  1. Create a field in the object, called say "NeededRecompute" that is
    read-only to all profiles and not in the layout
  2. In Before Update trigger, set these fields to false if no need for After Update trigger to do anything, and set to true if After Update should do something.
  3. In After update trigger, use this field to decide if there is something to do
1
  • 2
    Using a field to store this data is bad for a number of reasons. Using a static variable is more reliable for this purpose. For example, even though it's read-only, system admins could still update it via the API. Or create a workflow rule to update the field, potentially with side effects. Your limited to how many fields you can have per object, too, so this isn't a scalable solution. There's better ways to do this, so I would recommend that you don't.
    – sfdcfox
    Commented Jun 18, 2017 at 16:42

You must log in to answer this question.

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