0

I have a before update trigger on an object which does some validations and throws .addError in certain scenarios. This object has a process builder as well which updates certain fields on object. I do not want to execute the section of code in this trigger if this is being executed during update from process builder. How to achieve this.

2

I would think this could work however it is al or nothing kind of solution :

In your Invocable method, when calling from the process builder pass in a true value:

public static pbStartedThis = false;

@InvocableMethod
public static void doSomething(Some value, boolean isPB){
     if(isPB == true) pbStartedThis = true;
}

Then in the trigger that you do not want to run if the PB initiated the trigger

if(ClassName.pbStartedThis) return;

This will:

  1. Prevent the trigger from running if PB started the current iteration of the trigger
  2. Allow you to test it by passing in true or false
  3. Allow the trigger to run if initiated from other entry points up until the PB is executed

Note If the entry point is not from the PB but that causes the PB to fire then the trigger will not run after the PB calls the invocable method. If you need this to only happen if the PB was the entry point then you would have to use another static boolean to indicate things have started and return the evaluation of both booleans to decide to run the trigger or not.

This is off the top of my head and there may be better ways or maybe a review of the design to consider doing it completely differently.

As previously mentioned, PB and triggers should not really intersect. If either on them running depend on the other you should rethink your design as by nature the order is undetermined

1

I don't think there is a good way to know whether or not your trigger is being executed as a result of Process Builder. The same issue has plagued people for years with Workflow Field Updates (which are similarly difficult to know if a record is going through a trigger again because of them).

Mixing Process Builder and Triggers is a recipe for disaster, and I'd advise to choose one or the other.

If that's not a possibility, about the only suggestion I can come up with is to use a static Set<Id> in some Apex class (static variables in triggers are completely useless). In the code that you don't want to run again when the trigger is re-run after Process Builder, you would wrap the code in an if(alreadyRunSet.contains(myRec.Id)) block, and add myRec.Id to the Set<Id> somewhere inside the block.

That would cause that section of code to be run, at most, once per transaction. This method can't discriminate against how your trigger was caused to run more than once for the same record, so it would take affect for trigger interactions with other objects that invoke the trigger again, workflow rule field updates, and Process Builder.

If Process Builder is the first thing that causes this trigger of yours to run, however, then this method won't work for you because it only works to stop running code more than once.

1

I don't believe there is a way to check if process builder is running/executed that transaction via apex - however, you could accomplish this with small modifications to your object, process builder, and apex class/method.

First, create a new Number Field on your Object. Make it visible to all profiles, but don't put it on your page layouts. In this example I am calling my new field Workflow Update Counter

Second, update your process builder. Add a new field update to your existing updates for your Object. The field you are updating is Workflow Update Counter, and you can use the following formula as the update criteria: BLANKVALUE([YourObjectNameHere].Workflow_Update_Counter__c, 0) + 1

Lastly, update your apex method(s) and add a check to compare the newMap (or newList) with the oldMap, to check if the Workflow Update Counter field has been changed. If it has been changed, you know that your process builder ran in this transaction and you can stop it from proceeding (or do whatever other logic you want). Something like this:

if(record.Workflow_Update_Counter__c == oldMap.get(record.Id).Workflow_Update_Counter__c){
    // Since the new record and old record have the same value, 
    // the process builder did not run - execute code.
    // execute your code here
}

OR

if(record.Workflow_Update_Counter__c != oldMap.get(record.Id).Workflow_Update_Counter__c){
    // the workflow counter has changed via process builder, skip this record early
    continue;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.