Trigger Execution Flow - mouttaqui/AOF GitHub Wiki
The Apex Orbit Framework (AOF) establishes a clear and predictable execution flow for trigger-based logic. Understanding this flow is crucial for developers working with the framework.
1. DML Operation Occurs:
A Data Manipulation Language (DML) operation (e.g., insert, update, delete) is performed on an SObject record, either through the Salesforce UI, an API call, or Apex code.
2. SObject Trigger Fires:
The single, dedicated trigger for that SObject (e.g., AccountTrigger.trigger
) fires in response to the DML operation.
AOF_TriggerHandler
:
3. Instantiate The SObject trigger contains minimal logic. Its primary responsibility is to instantiate the AOF_TriggerHandler
class, passing the SObjectType of the current record(s) and the Trigger.operationType
.
apex // Example from AccountTrigger.trigger AOF_TriggerHandler handler = new AOF_TriggerHandler(Account.SObjectType, Trigger.operationType);
AOF_TriggerHandler.run()
:
4. Invoke The SObject trigger then calls the run()
method on the instantiated AOF_TriggerHandler
.
apex // Example from AccountTrigger.trigger handler.run();
AOF_TriggerHandler.run()
Execution:
5. This central method orchestrates the main logic:
- Bypass Check: It first checks if any bypass mechanisms are active (either a global bypass for all triggers or a specific bypass for the current SObjectType). If a bypass is active, the handler exits, and no further framework logic is executed for this transaction context.
- Context Determination: The handler identifies the exact trigger context (e.g.,
before insert
,after update
) using theTrigger.operationType
and other trigger context variables (Trigger.isBefore
,Trigger.isInsert
, etc.). - Domain/Service Layer Invocation: Based on the SObjectType and the trigger context, the
AOF_TriggerHandler
dynamically instantiates the appropriate SObject-specific Domain class (e.g.,AOF_AccountDomain
forAccount.SObjectType
). It then calls the corresponding context-specific method on the Domain class instance (e.g.,domainInstance.onBeforeInsert()
,domainInstance.onAfterUpdate()
). - The Domain class constructor receives the relevant records from the trigger context (e.g.,
Trigger.new
,Trigger.oldMap
). - For more complex operations that span multiple SObjects or involve external systems, the Domain class method might delegate to a method in a Service Layer class.
- Bulkification Ensured: All logic within the Domain and Service layers is designed to operate on collections of records, ensuring bulkification is maintained throughout the execution path.
6. Data Access and DML Registration:
- Selector Layer Usage: When Domain or Service layer methods need to query additional data, they utilize methods from the SObject-specific Selector classes (e.g.,
AOF_AccountSelector.selectActiveAccountsByType("Customer")
). Selector methods handle SOQL construction, FLS/CRUD enforcement, and return bulkified results. - Unit of Work Registration: If any DML operations (insert, update, delete) are required as a result of the business logic, these operations are not performed immediately. Instead, the SObject records are registered with the
AOF_Application_UnitOfWork
instance associated with the current transaction (e.g.,uow.registerNew(newContact)
).
7. Commit DML Operations:
- After all
before
andafter
logic for the current trigger context has been executed within the Domain and Service layers, and if no critical, unrecoverable errors have occurred (typically checked byrecord.hasErrors()
inbefore
contexts), theAOF_TriggerHandler
(or a top-level service method if the flow is more complex) calls thecommitWork()
method on theAOF_Application_UnitOfWork
instance. - The
commitWork()
method then executes all registered DML operations in a bulkified manner (e.g., a singleinsert
statement for all new records, a singleupdate
for all dirty records).
8. Error Handling:
- Throughout the execution flow, if an exception occurs, it should be caught at an appropriate level (e.g., within a service method, a domain method, or the
AOF_TriggerHandler
itself). - The
AOF_ErrorHandlerService.logError(...)
method is then called to publish anErrorLogEvent__e
Platform Event. This event contains details about the error (exception message, stack trace, class/method origin, involved records, etc.). - The Platform Event is processed asynchronously by a subscriber trigger (
ErrorLogEventTrigger
), which creates a persistentError_Log__c
record. This ensures error logging even if the main transaction rolls back. - For user-facing errors (e.g., validation rule failures), the
addError()
method should be used on the SObject record itself (e.g.,acc.Name.addError("Account Name cannot be blank.")
). This prevents the record from being saved and displays the error to the user in the UI.
This structured flow ensures that trigger logic is organized, manageable, bulk-safe, and adheres to Salesforce best practices.