Bypass Apex Trigger in Flow Transaction

Each flow interview runs in the context of a transaction. A transaction is a collection of operations that are performed as a single unit. In addition to a flow interview, a transaction can execute Apex triggers and escalation rules.

💼 Use Case

You’ve developed a flow that executes whenever something changes in the Account object and you’re updating its associated contact object. There is an Apex Trigger written on the contact object, which you do not want to execute when updating records from the flow.

✅ Solution

Create an Apex class

/***********************************************************************************
Class Name : TriggerSwitchCls
Description : This class can be used to stop the trigger execution for a transaction.
Created By : SFDC Lessons
Created Date : 09/06/2022
Modification Logs:
------------------------------------------------------------------------------------
Developer Date Descriptions
-------------------------------------------------------------------------------------
Arun Kumar 09/06/2022 Initial version
*************************************************************************************/
public class TriggerSwitchCls {
public static Boolean accountTriggerRunFlag = true;
public static Boolean opportunityTriggerRunFlag = true;
public static Boolean contactTriggerRunFlag = true;
public static Boolean opportunityLineItemTriggerRunFlag = true;
public static Boolean userTriggerRunFlag = true;
public static Boolean leadTriggerRunFlag = true;
//Account Trigger Switch Logic
public static Boolean canAccountTriggerExecute(){
return accountTriggerRunFlag;
}
public static void stopAccccountTrigger(){
accountTriggerRunFlag = false;
}
public static void allowAccountTrigger(){
accountTriggerRunFlag = true;
}
//Opportunity Trigger Switch Logic
public static Boolean canOpportunityTriggerExecute(){
return opportunityTriggerRunFlag;
}
public static void stopOpportunityTrigger(){
opportunityTriggerRunFlag = false;
}
public static void allowOpportunityTrigger(){
opportunityTriggerRunFlag = true;
}
//Contact Trigger Switch Logic
public static Boolean canContactTriggerExecute(){
return contactTriggerRunFlag;
}
public static void stopContactTrigger(){
contactTriggerRunFlag = false;
}
public static void allowContactTrigger(){
contactTriggerRunFlag = true;
}
//OpportunityLineItem Trigger Switch Logic
public static Boolean canOLITriggerExecute(){
return opportunityLineItemTriggerRunFlag;
}
public static void stopOLITrigger(){
opportunityLineItemTriggerRunFlag = false;
}
public static void allowOLITrigger(){
opportunityLineItemTriggerRunFlag = true;
}
//User Trigger Switch Logic
public static Boolean canUserTriggerExecute(){
return userTriggerRunFlag;
}
public static void stopUserTrigger(){
userTriggerRunFlag = false;
}
public static void allowUserTrigger(){
userTriggerRunFlag = true;
}
//Lead Trigger Switch Logic
public static Boolean canLeadTriggerExecute(){
return leadTriggerRunFlag;
}
public static void stopLeadTrigger(){
leadTriggerRunFlag = false;
}
public static void allowLeadTrigger(){
leadTriggerRunFlag = true;
}
//** Duplicate the above methods for other objects */
}

The above class method can be used to stop the trigger execution.

Advertisements

Contact Trigger

In line 11, you can see that I used the TriggerSwitchCls method to determine whether the trigger code should be executed or not. This method returns TRUE or FALSE depending on the static boolean variable set in the method.

/**
* @description ContactTrigger.
* @Created By: Arun Kumar
* @Created Date : 26-06-2022
* @Last Modified Date : 26-06-2022
*/
trigger ContactTrigger on Contact (before insert,before update, before delete, after insert, after update, after delete,after undelete) {
// This "TriggerSwitchCls.canContactTriggerExecute()" will return TRUE or FALSE. By default it will return TRUE and
//if we bypass this in flow then it will return FALSE and trigger will be bypassed.
if(TriggerSwitchCls.canContactTriggerExecute()){
System.debug('Inside Contact Trigger');
TriggerHandler handler = new ContactTriggerHandler(Trigger.isExecuting, Trigger.size);
switch on Trigger.operationType {
when BEFORE_INSERT {
//call before insert handler method
handler.beforeInsert(Trigger.new);
}
when BEFORE_UPDATE {
//call before update handler method
handler.beforeUpdate(Trigger.new, Trigger.old, Trigger.newMap, Trigger.oldMap);
}
when BEFORE_DELETE{
//call before delete handler method
handler.beforeDelete(Trigger.old, Trigger.oldMap);
}
when AFTER_INSERT{
//call after insert handler method
handler.afterInsert(Trigger.new,Trigger.newMap);
}
when AFTER_UPDATE{
//call after update handler method
handler.afterUpdate(Trigger.new, Trigger.old, Trigger.newMap, Trigger.oldMap);
}
when AFTER_DELETE{
//call after delete handler method
handler.afterDelete(trigger.old, Trigger.oldMap);
}
when AFTER_UNDELETE{
//call after undelete handler method
handler.afterUndelete(trigger.new, Trigger.newMap);
}
}
}
}
Advertisements

Now create two different classes to stop and allow the trigger from flow transaction. Each class will have an invocable method that calls the TriggerSwitchCls method to set the static boolean variable to TRUE or FALSE.

StopTriggerHandler.cls

/***********************************************************************************
Class Name : StopTriggerHandler
Description : This class can be used in the PB, flow to do the actions defined in the methods.
Created By : SFDC Lessons
Created Date : 09/06/2022
Modification Logs:
------------------------------------------------------------------------------------
Developer Date Descriptions
-------------------------------------------------------------------------------------
Arun Kumar 09/06/2022 Initial version
*************************************************************************************/
public class StopTriggerHandler {
/**
* @description stopTrigger method can be called from PB/FLOWs to stop the object trigger for a transaction.
* @param triggerNameToStop
*/
@InvocableMethod(label='Stop sObject Trigger' description='Stop the sObject trigger for this transaction')
Public static void stopTrigger(List<List<String>> triggerNameToStop){
for(String varTrggrName: triggerNameToStop[0]){
//switch statement checking trigger name and stoping the triggers
switch on varTrggrName {
when 'Account' {
TriggerSwitchCls.stopAccccountTrigger();
}
when 'Opportunity' {
TriggerSwitchCls.stopOpportunityTrigger();
}
when 'Contact' {
TriggerSwitchCls.stopContactTrigger();
}
when 'OpportunityLineItem' {
TriggerSwitchCls.stopOLITrigger();
}
when 'User' {
TriggerSwitchCls.stopUserTrigger();
}
when 'Lead' {
TriggerSwitchCls.stopLeadTrigger();
}
}//switch statement block ends here
}//for loop ends here
system.debug('Can Opportnity Trigger Execute ? : ' + TriggerSwitchCls.canAccountTriggerExecute());
}//mehod ends here
}

AllowTriggerHandler.cls

/***********************************************************************************
Class Name : AllowTriggerHandler
Description : This class can be used in the PB, flow to do the actions defined in the methods.
Created By : SFDC Lessons
Created Date : 09/06/2022
Modification Logs:
------------------------------------------------------------------------------------
Developer Date Descriptions
-------------------------------------------------------------------------------------
Arun Kumar 09/06/2022 Initial version
*************************************************************************************/
public class AllowTriggerHandler {
/**
* @description stopTrigger method can be called from PB/FLOWs to allow the sObject trigger for a transaction.
* @param triggerNameToAllow
*/
@InvocableMethod(label='Allow sObject Trigger to execute' description='Allow the sObject trigger for this transaction')
Public static void allowTrigger(List<List<String>> triggerNameToAllow){
for(String varTrggrName: triggerNameToAllow[0]){
//switch statement checking trigger name and stoping the triggers
switch on varTrggrName {
when 'Account' {
TriggerSwitchCls.allowAccountTrigger();
}
when 'Opportunity' {
TriggerSwitchCls.allowOpportunityTrigger();
}
when 'Contact' {
TriggerSwitchCls.allowContactTrigger();
}
when 'OpportunityLineItem' {
TriggerSwitchCls.allowOLITrigger();
}
when 'User' {
TriggerSwitchCls.allowUserTrigger();
}
when 'Lead' {
TriggerSwitchCls.allowLeadTrigger();
}
}//switch statement block ends here
}//for loop ends here
}//mehod ends here
}

To stop the object trigger execution, call the invocable method stopTrigger(objectName) in the flow. You simply need to pass the name of the object for which you want to bypass the trigger.

Advertisements

🚶Steps to Implement the Solution in Flow

Click on the New Resources button in the flow builder and create a collection variable to store the object name.

Enter the API Name, description and select the checkbox to allow multiple values (collection).

The next step is to add values to this collection.

Select the assignment element and add the string ‘Contact‘ to this variable.

Add an Action element before the Update Record element.

In the Action lookup field selects the “Stop sObject Trigger” invocable action.

Enter the label and API name, then enable the toggle button and select the collection variable in the triggerNameToStop field.

After Update Records element, add Apex action to allow the Contact trigger to execute.

Select ‘Allow sObject Trigger to execute‘ apex action.

Enter the label and API name, then enable the toggle button and select the collection variable in the triggerNameToStop field.

Finally, the flow will look like the screenshot below.

When flow updates a contact record, the contact trigger no longer executes.

Advertisements

Summary

You may have encountered the CPU time limit exceeded if you doing a bulk record upload. This is usually due to multiple automation tools (Flow, PB, Trigger) running and not being developed properly. If you look at the debug log, you might notice that the DML you’re doing in the flow again calls the apex trigger/PB. We can bypass and allow apex trigger in flow transactions with the help of the apex invocable method a boolean static variable. However, automation tools should be written in such a way that they do not call each other back and forth, and proper conditions should be added to trigger code to execute the code in the exact use case.

Join 768 other followers
Advertisements
Advertisements
  • Event-Driven Integrations Just Got Easier with the Pub/Sub API
    The Pub/Sub API provides a unified interface for publishing and subscribing to platform events such as real-time event monitoring and change data capture. Pub/Sub API efficiently publishes and delivers binary event messages in the Apache Avro format using gRPC and HTTP/2.
  • In and Not In Operators in Flows
    Salesforce’s Winter’23 release included this much-needed feature ↠ In and Not In operators in flow builder. With In and Not in operators, we can easily query the related data without writing a query inside the loop element.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s