Triggers and order of execution
In this post I want to review the order in which things happen when I save a record in Salesforce. This is important to understand if you are an app builder who works automating processes as well as if you are a developer that writes trigger code. Both worlds will converge in the end and affect each other, so you have to bear in mind how Salesforce executes things internally to ensure a correct behaviour of your solution.
My recommendation is that you first read the explanation about the execution order without going to the examples, and then you re-read it again taking a look at the examples, that will clarify how this works.
Per the documentation, the order of execution when a record is saved is the next one:
STEP 1: System Validation Rules are executed. This includes:
- Verifying that required fields have a value
- Valid field formats
- Maximum field length
- Foreign keys are valid
Additionally, if the save operation has been called from a standard UI, it will be checked:
- Compliance with layout-specific rules
- Required values at the layout level
If system validations fail at this stage, next steps will never be executed. See example 1.
STEP 2: Apex before triggers are executed. Indeed, if an error occurs in a before trigger, the following steps won’t be performed.
- Bear in mind as well that if there are several before triggers, the order of execution of them in not guaranteed.
- Before triggers is the correct place to derive field values, as the record can still be edited.
- Before triggers is not the correct place to perform Apex validations, as any other before triggers could execute after yours and change the record, skipping your validations. This problem is known as the evil trigger problem.
If a validation is thrown in a before trigger, next steps will never be executed. See example 2.
STEP 3: System Validation Rules are executed again, except layout specific rules. This means that if my before trigger did something that left the record in a non valid state, for example emptying a required field, at this point the execution will stop, because it will be re-validated.
System validations validate changes performed in before trigger. If system validations fail at this stage, next steps will never be executed. See example 3.
STEP 4: Custom Validation Rules are executed. Custom validation rules are the rules that you can define declaratively in the platform, that will throw an error if certain conditions are meet on record save.
Any changes that I perform in the before trigger will be validated by my custom validation rules.
Custom validation rules validate changes performed in before trigger. If custom validations fail, next steps will never be executed. See example 4.
STEP 5: Record is saved to database (but not committed)
STEP 6: All Apex after triggers execute. At this point the record is not editable anymore, as it was in before triggers.
- Again, the execution order of after triggers if there are several in your org is not guaranteed.
- This is the correct place to perform Apex validations, as the record can’t be changed anymore and evil trigger problem won’t happen.
If a validation is thrown in an after trigger, next steps, as workflow rules, will never be executed.
STEP 7: Assignment rules are executed. Assignment rules are rules that you can define declaratively to assign Leads and Cases to a specific user or queue based in certain criteria when they are created. See this post for more information.
STEP 8: Auto-response rules are executed. Auto-Response Rules allow you to generate an email automatically in response to an incoming Lead or Case. Learn more here.
STEP 9: Workflow rules are executed. Workflow rules is one of the ways we have in the platform to automate processes declaratively. With workflow rules you can do the following:
- Assign a new task to a user, role, or record owner.
- Send an email to one or more recipients you specify.
- Update the value of a field on the record that is being saved, or in a related object.
- Send a secure, configurable API message (in XML format) to a designated listener (outbound message).
As a workflow rule can update the record that has already been saved, if this situation happens, system validations, before and after triggers are executed again. However custom validation rules are not executed again. See examples 5 and 6.
This means that a custom validation rule can be surpassed if I update the field to which the validation affects through a workflow rule field update. This applies also to workflow field updates that run based on an approval process or time-dependent action.
If a Workflow Rule uses a Formula Field in its criteria or formula, the formula field is evaluated when the Workflow Rule criteria is checked. This is, as the workflow rule is executed after the record has been saved to the database, the formula field will be evaluated against trigger.new version of the object, and not against the old one.
STEP 10: Processes built with Process Builder. If there are workflow flow triggers, executes the flows. Workflow flow triggers give the ability of launching flows from a workflow rule. This feature was available through a pilot program. Now it seems to have been substituted by flow actions in Process Builder.
As process can update the record that has already been saved, if this situation happens,system validations, custom validation rules, before and after triggers are executed again. See examples 7 and 8.
This means that my trigger can be executed three times: the initial one, after a workflow rule has been executed, and after a process has been executed. Check this interesting post to know more.
Notice here that, in this situation, custom validation rules will be executed, in contrast with workflow rule field updates.
STEP 11: Escalation rules are executed. These are rules for automatically escalating cases when a certain criteria is meet. Read more here.
STEP 12: Entitlement rules are executed. These rules include all of the steps (or milestones) that your support team must complete to resolve cases. Read more here.
STEP 13: Parent Rollup Summary Formula value are updated (if present):
- If the record contains a roll-up summary field or is part of a cross-object workflow, performs calculations and updates the roll-up summary field in the parent record. Parent record goes through save procedure.
- If the parent record is updated, and a grandparent record contains a roll-up summary field or is part of a cross-object workflow, performs calculations and updates the roll-up summary field in the grandparent record. Grandparent record goes through save procedure.
STEP 14: Data is committed to the database.
STEP 15: All post-commit logic is executed, for example sending emails, etc.
I have created this schema to help understanding what is happening behind the scenes.
Additional considerations:
If the number of objects that arrive to a trigger is greater than 200 on a bulk DML operation, the trigger execution will be chunked. This is, trigger will process records in chunks of 200. This will multiply the number of DML operations, SOQL queries and CPU time performed in the trigger by the number of times it is executed. And this will count towards the limits per transaction! Know more in this trailhead unit.
EXAMPLES
Example 1: System validation executed in first place prevents execution of next steps
This is an example of a system validation rule:
If a previous system validation happen, before trigger will never be executed. For example, if I create a validation in a before trigger:
trigger AccountTrigger on Account (before insert) { if (Trigger.isBefore) { for (Account a : Trigger.new) { if (a.Name.length() < 5) a.Name.addError('Account name is too short.'); } } }
And I do the same test I will obtain the same result I obtained before, as system validation rule will go first and prevent my before trigger validation from being executed. Any further steps would be prevented too.
Example 2: Before trigger validation prevents execution of next steps
If a validation is thrown in a before trigger, next steps, as custom validation rules or after triggers, will never be executed.
Let’s see an example of this. In my org I have created a validation rule that prevents storying an account whose name contains an “x”. My account trigger is deactivated at this point.
If I try to insert an account whose name is “xy”, the validation rule appears:
What happens if I activate my account trigger, which now contains two validations (one on the before insert part, and the other on the after insert part) ?
trigger AccountTrigger on Account (before insert, after insert) { if (Trigger.isBefore) { for (Account a : Trigger.new) { if (a.Name.length() < 5) a.Name.addError('Account name is too short.'); } } else { for (Account a : Trigger.new) { if (a.Name.contains('y')) a.Name.addError('Account name contains a y.'); } } }
If I perform the same tests, neither my validation rule nor the validation on the after part are executed, because error on before part prevented them:
Example 3: System validation executed after before trigger prevents execution of next steps
Again a failure at this stage will prevent next steps from occur. We can check creating the next trigger:
trigger AccountTrigger on Account (before insert, after insert) {
if (Trigger.isBefore) { for (Account a : Trigger.new) { a.Name = ''; } } else { for (Account a : Trigger.new) { if (a.Name.length()==0) a.Name.addError('Account name is empty.');
} } }
Now if we try to insert an account with any name:
We see that the system validation rule was executed after the before trigger part, which emptied the account name. Also the system validation rule prevented the execution of the after part validation or any further steps.
Example 4: Custom validation rule prevents execution of next steps
Let’s see another example for this. Let’s modify the account before trigger to set an “x” specifically in the account name.
trigger AccountTrigger on Account (before insert, after insert) { if (Trigger.isBefore) { for (Account a : Trigger.new) { a.Name = 'xxx'; }
} else { for (Account a : Trigger.new) { if (a.Name == 'xxx') a.Name.addError('Account name is xxx.'); } } }
What would happen then if a try to save this account?
The validation rule I created has been executed and checked the account after having been modified by the before insert trigger. Validation on after part or any further steps are prevented as well.
Example 5: After trigger validation is executed after workflow rule field update
In this case I have a created a workflow rule for account object, that will set account name as ‘xxx’ in any situation.
Also I have edited my trigger to be the following:
trigger AccountTrigger on Account (after update) { if (Trigger.isAfter) { for (Account a : Trigger.new) { if (a.Name == 'xxx') a.Name.addError('Account name is xxx.'); } } }
Notice that as my workflow rule is going to update my record once it was saved to the database, I have had to add the validation on update, rather than on insert, to test this.
If I try now to insert an account:
My system validations, custom validations and triggers are executed once, the record is saved to the database, and my workflow rule updates it again. Then, system validations and triggers are executed again, and the after update validation is thrown.
Example 6: Custom validation rule is not executed after workflow rule field update
Let’s try the same using a validation rule instead of an Apex validation on the after trigger. I activate the validation rule I created for example 2:
This time, if I try to save an account which name is ‘a’, my system validations, custom validations and triggers are executed once, the record is saved to the database, and my workflow rule updates it again to be ‘xxx’. This time the custom validation rule does not execute again. So, the record is saved to the database!
Example 7: After trigger validation is executed after process builder field update
For this example I have:
- Added a debug log to my trigger in order I can see how many times it is called
- Modifed my workflow rule field update, to update the account name to another value that is allowed (‘bbb’).
- Created a simple process in process builder that sets my account name to ‘xxx’ on insert (remember we are validating this on after update trigger).
trigger AccountTrigger on Account (after insert, after update) { if (Trigger.isAfter) { for (Account a : Trigger.new) { System.debug(Logginglevel.error, 'Account name: ' +a.name); if (a.Name == 'xxx') a.Name.addError('Account name is xxx.'); } } }
What happens when I try to create an account which name is ‘a’?
After trigger executes three times (initial, workflow rule field update and process field update). I receive an error, provoked by the third after trigger execution, after my process set the account name to ‘xxx’ . This is the debug log I obtain:
Example 8: Custom validation rule is executed after process builder field update
In this last example, what I have done is to deactivate the trigger and substitute it by a custom validation rule that checks my name does not contain an ‘x’.
The result is exactly the same as before: I receive an error on save, which means, after my process set the name to ‘xxx’, custom validation rule was executed again.
Notice that this time before trigger was executed three times, but after trigger only two, because the custom validation rule prevented the process from continuing.
If you want to know more about order of execution in Salesforce, you can check the official documentation.
No comments:
Post a Comment