Best Practice Series
Apex Trigger Framework
Presented by
Joseph Msallem
Nicole Tannous
Ziad Azoury
1
Copyright © 2020 EI-Technologies-Lebanon SAL.
Apex Trigger Framework
Plan
01 Current Triggers Best Practices
02 What is a Salesforce Apex trigger framework
03 Apex Trigger Framework Architecture
04 What do we need to develop an Apex Trigger Framework
05 Benefits of an Apex Trigger Framework
06 Demo
2
Copyright © 2020 EI-Technologies-Lebanon SAL.
Apex Trigger Framework
Current Trigger Best Practice v2,0
• The trigger contains only one combination of type(isBefore /
Triggers isAfter) and DML (isInsert / isUpdate / isDelete)
(Best Practice v2,0) • We also had the PAD ByPass while verifying the DML. We can
also bypass by method.
3
Copyright © 2020 EI-Technologies-Lebanon SAL.
Apex Trigger Framework
Current Trigger Best Practice v2,0
trigger AccountTrigger on Account (before insert){
if([Link]('AccountBeforeInsert’)){
if([Link]('AccountBeforeInsertMethode01’)){
AP01Account.myMethodeAccBeforeInsert01([Link], [Link]);
}
if([Link]('AccountBeforeInsertMethode02’)){
AP01Account.myMethodeAccBeforeInsert02([Link], [Link]);
}
}
}
trigger AccountTrigger on Account (after insert){
if([Link]('AccountAfterInsert’)){
if([Link]('AccountAfterInsertMethode01’)){
AP01Account.myMethodeAccAfterInsert01([Link], [Link]);
}
}
}
trigger AccountTrigger on Account (before Update){
if([Link]('AccountBeforeUpdate’)){
if([Link]('AccountBeforeUpdateMethode01’)){
AP01Account.myMethodeAccBeforeUpdate01([Link], [Link]);
}
}
}
4
Copyright © 2020 EI-Technologies-Lebanon SAL.
Apex Trigger Framework
Current Trigger Best Practice v3,0
• The trigger must contain only the instantiation of the
corresponding handler class, the isBefore / isAfter, and the the
Triggers verification of DMLs isInsert / isUpdate / isDelete
(Best Practice v3,0) • We also had the PAD ByPass while verifying the DML. We can
also bypass by method.
5
Copyright © 2020 EI-Technologies-Lebanon SAL.
Apex Trigger Framework
Current Trigger Best Practice v3,0
trigger AccountTrigger on Account (before insert, before update, before delete, after insert, after update){
AccountTriggerClass ATC = new AccountTriggerClass();
if([Link]){
if([Link] && [Link]('AccountBeforeInsert’)){
[Link]([Link]);
}
if([Link] && [Link]('AccountBeforeUpdate')){
if([Link]('AccountBeforeUpdateMethode01'))
ATC.myMethodeBeforeUpdate01([Link], [Link]);
if([Link]('AccountBeforeUpdateMethode02'))
ATC.myMethodeBeforeUpdate02([Link]);
}
if([Link] && [Link]('AccountBeforeDelete')){
[Link]([Link]);
}
}
if([Link]){
if([Link] && [Link]('AccountAfterInsert')){
if([Link]('AccountAfterInsertMethode01'))
ATC.myMethodeAfterInsert01([Link], [Link]);
if([Link]('AccountAfterInsertMethode02'))
ATC.myMethodeAfterInsert02([Link]);
}
if([Link] && [Link]('AccountAfterUpdate')){
[Link]([Link]);
}
}
}
6
Copyright © 2020 EI-Technologies-Lebanon SAL.
Apex Trigger Framework
Definition
The trigger framework The base class includes
bundles a single context-specific methods
TriggerHandler base class that are automatically
that you can inherit from called when a trigger is
in all your trigger handlers executed
The base class also The most important part
provides a secondary role of this framework is that
as a supervisor for Trigger it's minimal and simple to
execution use
7
Copyright © 2020 EI-Technologies-Lebanon SAL.
Apex Trigger Framework
Apex Trigger Framework Architecture
SObject Interface
ITriggerHandler
DML Business Logic
<sObject>Trigger Implements
Calls
Calls Dynamic Binding
<sObject>TriggerHandler
TriggerDispatcher
Run (ITriggerHandler handler)
Copyright © 2020 EI-Technologies-Lebanon SAL.
Apex Trigger Framework
Utils
Interface Trigger Error Handling
Dispatcher
Contains all trigger
SERVICES
Sits between Apex Another Apex Class
context method Trigger and handler which create the Error
class and routes to logs and Stores in a
correct method or custom Object
Handler class
9
Copyright © 2020 EI-Technologies-Lebanon SAL.
Apex Trigger Framework
Steps to create it
01 Each trigger must be implemented in a custom metadata that allows the trigger to be
active/inactive from UI.
10
Copyright © 2020 EI-Technologies-Lebanon SAL.
Apex Trigger Framework
Steps to create it
02 Create a record for each trigger
02 Lorem Ipsum
03 Lorem Ipsum
04 Lorem Ipsum
11
Copyright © 2020 EI-Technologies-Lebanon SAL.
Apex Trigger Framework
Steps to create it
03 Create a Trigger Handler Interface
Public interface ITriggerHandler{
void beforeInsert();
02
void afterInsert();
void beforeUpdate();
Lorem Ipsum
void afterUpdate();
void beforeDelete();
void afterDelete();
void afterUnDelete();
Boolean isDisabled();
03
}
Lorem Ipsum
04 Lorem Ipsum
12
Copyright © 2020 EI-Technologies-Lebanon SAL.
Apex Trigger Framework
Steps to create it
04 Create the dispatcher
This is a part of the dispatcher code
You can check the complete code from the link below:
[Link]
NB: Check the API version is always 51 or higher
04 Lorem Ipsum
13
Copyright © 2020 EI-Technologies-Lebanon SAL.
Apex Trigger Framework
Steps to create it
05 Create the SObject Trigger Handler extending the Trigger Handler and implementing the Trigger
Handler Interface
public class SObjectNameTriggerHandler extends TriggerHandler implements ITriggerHandler{
private Map<Id, SObject> newMap;
private Map<Id, SObject> oldMap;
private List<SObject> triggerNew;
Lorem List<SObject>
private Ipsum triggerOld;
public SObjectNameTriggerHandler(){
[Link] = (Map<Id, SObject>) [Link];
[Link] = (Map<Id, SObject>) [Link];
[Link]= (List<SObject>) [Link];
[Link]= (List<SObject>) [Link];
03
}
public static Boolean TriggerDisabled = false;
LoremBoolean
public IpsumisDisabled(){
return TriggerDisabled;
}
public override void beforeInsert() {}
public override void afterInsert() {}
04
public override void beforeUpdate() {}
Loremoverride
public Ipsum void afterUpdate() {}
public override void beforeDelete() {}
public override void afterDelete() {}
public override void afterUnDelete() {}
14
Copyright © 2020 EI-Technologies-Lebanon SAL.
Apex Trigger Framework
Steps to create it
06 Create the Sobject’s trigger
/*
@Author : TMA NTA
@CreatedDate : 11-02-2021
@Description : SObjectName Trigger.
*/
trigger SObjectNameTrigger on SObject(before insert, after insert, before update, after update, before delete, after
delete, after unDelete) {
new SObjectNameTriggerHandler().run();
}
15
Copyright © 2020 EI-Technologies-Lebanon SAL.
Apex Trigger Framework
Benefits
A single trigger per object gives complete
control over the order of execution
Implementing trigger logic in handler class,
makes unit testing and maintenance much
easier
Implementation of best practices
It allows to prevent trigger recursion without
adding separate logic
It is easier to work on a single trigger for
multiple developers and reduce the
development lifecycle
It allows to make decisions to active/inactive
the trigger from transaction and UI as well
16
Copyright © 2020 EI-Technologies-Lebanon SAL.
Apex Trigger Framework
Cool features
Max Loop Count
06
To prevent recursion, you can set a public class OpportunityTriggerHandler extends TriggerHandler {
max loop count for Trigger public OpportunityTriggerHandler() {
[Link](1);
Handler. If this max is exceeded, }
and exception will be thrown. A public override void afterUpdate() {
List<Opportunity> opps = [SELECT Id FROM Opportunity WHERE Id IN:[Link]()];
great use case is when you want to }
update opps; // this will throw after this update
}
ensure that your trigger runs once
and only once within a single
execution. Example:
17
Copyright © 2020 EI-Technologies-Lebanon SAL.
Apex Trigger Framework
Cool features
Bypass API
What if you want to tell other trigger handlers to halt execution? That's easy with the bypass api:
public class OpportunityTriggerHandler extends TriggerHandler {
public override void afterUpdate() {
List<Opportunity> opps = [SELECT Id, AccountId FROM Opportunity WHERE Id IN :[Link]()];
Account acc = [SELECT Id, Name FROM Account WHERE Id = :[Link](0).AccountId];
[Link]('AccountTriggerHandler’);
[Link] = 'No Trigger’;
update acc; // won't invoke the AccountTriggerHandler
[Link]('AccountTriggerHandler’);
[Link] = 'With Trigger’;
update acc; // will invoke the AccountTriggerHandler
}
}
If you need to check if a handler is bypassed, use the isBypassed method:
if ([Link]('AccountTriggerHandler')) {
// ... do something if the Account trigger handler is bypassed!
}
If you want to clear all bypasses for the transaction, simple use the clearAllBypasses method, as in:
// ... done with bypasses!
[Link]();
// ... now handlers won't be ignored!
18
Copyright © 2020 EI-Technologies-Lebanon SAL.
Apex Trigger Framework
Demo
DEMO
19
Copyright © 2020 EI-Technologies-Lebanon SAL.
Apex Trigger Framework
THANK YOU
ANY QUESTIONS?
20
Copyright © 2020 EI-Technologies-Lebanon SAL.
Apex Trigger Framework
References
[Link]
[Link]
[Link]
Copyright © 2020 EI-Technologies-Lebanon SAL.