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 795 other followers
Advertisements
Advertisements
  • Handle the X close button event in Lightning quick action modal
    In Salesforce Lightning, quick actions are a powerful way to improve the user experience by allowing users to perform common tasks from a single location. However, one issue that can arise when using quick actions is that it can be difficult to handle the event when the user closes the quick action.
  • 10 Best Practices for Writing Apex Test Classes in Salesforce – Examples Included
    Apex Test classes are an essential part of Salesforce development, as they help ensure that your code is functioning correctly and that your business logic is sound. In this blog post, we will go over best practices for Apex Test classes, including tips for writing efficient and effective tests, as well as examples of how to implement these best practices in your own code.

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