Tuesday, June 27, 2017

Salesforce Basics - Apex Triggers

A trigger can fire before or after DML operations.

Triggers have special variables accessible to them called context variables. In a nutshell, old and new context variables provide copies of old and new sObjects being updated by the call that fires the trigger. As you can see in the code, context variables are handy to scope processing in a trigger body.

In the FOR loop for Invoice Object for example, the trigger simply adds a validation error to any Invoice that has Line Items, which in turn causes the Force.com platform to roll back the transaction that fires the trigger (in this case, delete).

Apex can be invoked through the use of triggers. A trigger is Apex code that executes before or after the following types of operations:

insert
update
delete
merge
upsert
undelete

For example, you can have a trigger run before an object's records are inserted into the database, after records have been deleted, or even after a record is restored from the Recycle Bin.
You can define triggers for top-level standard objects that support triggers, such as a Contact or an Account, some standard child objects, such as a CaseComment, and custom objects.

For case comments, from Setup, click Customize | Cases | Case Comments | Triggers.
For email messages, from Setup, click Customize | Cases | Email Messages | Triggers.

There are two types of triggers:
Before triggers are used to update or validate record values before they’re saved to the database.
After triggers are used to access field values that are set by the system (such as a record's Id or LastModifiedDate field), and to effect changes in other records, such as logging into an audit table or firing asynchronous events with a queue. The records that fire the after trigger are read-only.

Triggers can also modify other records of the same type as the records that initially fired the trigger. For example, if a trigger fires after an update of contact A, the trigger can also modify contacts B, C, and D. Because triggers can cause other records to change, and because these changes can, in turn, fire more triggers, the Apex runtime engine considers all such operations a single unit of work and sets limits on the number of operations that can be performed to prevent infinite recursion. See Understanding Execution Governors and Limits.
Additionally, if you update or delete a record in its before trigger, or delete a record in its after trigger, you will receive a runtime error. This includes both direct and indirect operations. For example, if you update account A, and the before update trigger of account A inserts contact B, and the after insert trigger of contact B queries for account A and updates it using the DML update statement or database method, then you are indirectly updating account A in its before trigger, and you will receive a runtime error.

Implementation Considerations
Before creating triggers, consider the following:
upsert triggers fire both before and after insert or before and after update triggers as appropriate.
merge triggers fire both before and after delete triggers for the losing records and before update triggers for the winning record only. See Triggers and Merge Statements.
Triggers that execute after a record has been undeleted only work with specific objects. See Triggers and Recovered Records.
Field history is not recorded until the end of a trigger. If you query field history in a trigger, you will not see any history for the current transaction.
For Apex saved using Salesforce API version 20.0 or earlier, if an API call causes a trigger to fire, the chunk of 200 records to process is further split into chunks of 100 records. For Apex saved using Salesforce API version 21.0 and later, no further splits of API chunks occur. Note that static variable values are reset between API batches, but governor limits are not. Do not use static variables to track state information between API batches.

Order Of Execution Trigger events
UPSERT: Loads the original record from the database or initializes the record for an upsert statement.

UPDATE: If the record was updated with workflow field updates, fires before update triggers and after update triggers one more time (and only one more time), in addition to standard validations. Custom validation rules are not run again.

Triggers and Order of Execution
When you save a record with an insert, update, or upsert statement, Salesforce performs the following events in order.
Note
Before Salesforce executes these events on the server, the browser runs JavaScript validation if the record contains any dependent picklist fields. The validation limits each dependent picklist field to its available values. No other validation occurs on the client side.

On the server, Salesforce:
1) Loads the original record from the database or initializes the record for an upsert statement.
2) Loads the new record field values from the request and overwrites the old values.
If the request came from a standard UI edit page, Salesforce runs system validation to check the record for:
> Compliance with layout-specific rules
> Required values at the layout level and field-definition level
> Valid field formats
> Maximum field length
When the request comes from other sources, such as an Apex application or a SOAP API call, Salesforce validates only the foreign keys. Prior to executing a trigger, Salesforce verifies that any custom foreign keys do not refer to the object itself.
Salesforce runs user-defined validation rules if multiline items were created, such as quote line items and opportunity line items.
3) Executes all before triggers.
4) Runs most system validation steps again, such as verifying that all required fields have a non-null value, and runs any user-defined validation rules. The only system validation that Salesforce doesn't run a second time (when the request comes from a standard UI edit page) is the enforcement of layout-specific rules.
5) Executes duplicate rules. If the duplicate rule identifies the record as a duplicate and uses the block action, the record is not saved and no further steps, such as after triggers and workflow rules, are taken.
6) Saves the record to the database, but doesn't commit yet.
7) Executes all after triggers.
8) Executes assignment rules.
9) Executes auto-response rules.
10) Executes workflow rules.
11) If there are workflow field updates, updates the record again.
12) If the record was updated with workflow field updates, fires before update triggers and after update triggers one more time (and only one more time), in addition to standard validations. Custom validation rules and duplicate rules are not run again.
13) Executes processes.
If there are workflow flow triggers, executes the flows.
The Process Builder has superseded flow trigger workflow actions, formerly available in a pilot program. Organizations that are using flow trigger workflow actions can continue to create and edit them, but flow trigger workflow actions aren’t available for new organizations.
14) Executes escalation rules.
15) Executes entitlement rules.
16) 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.
17) 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.
18) Executes Criteria Based Sharing evaluation.
19) Commits all DML operations to the database.
20) Executes post-commit logic, such as sending email.

During a recursive save, Salesforce skips steps 8 (assignment rules) through 17 (roll-up summary field in the grandparent record).

Additional Considerations
Please note the following when working with triggers.

> The order of execution isn’t guaranteed when having multiple triggers for the same object due to the same event. For example, if you have two before insert triggers for Case, and a new Case record is inserted that fires the two triggers, the order in which these triggers fire isn’t guaranteed.
> When a DML call is made with partial success allowed, more than one attempt can be made to save the successful records if the initial attempt results in errors for some records. For example, an error can occur for a record when a user-validation rule fails. Triggers are fired during the first attempt and are fired again during subsequent attempts. Because these trigger invocations are part of the same transaction, static class variables that are accessed by the trigger aren't reset. DML calls allow partial success when you set the allOrNone parameter of a Database DML method to false or when you call the SOAP API with default settings. For more details, see Bulk DML Exception Handling.
> If you are using before triggers to set Stage and Forecast Category for an opportunity record, the behavior is as follows:
        > If you set Stage and Forecast Category, the opportunity record contains those exact values.
        > If you set Stage but not Forecast Category, the Forecast Category value on the opportunity record defaults to the one associated with trigger Stage.
        > If you reset Stage to a value specified in an API call or incoming from the user interface, the Forecast Category value should also come from the API call or user interface. If no value for Forecast Category is specified and the incoming Stage is different than the trigger Stage, the Forecast Category defaults to the one associated with trigger Stage. If the trigger Stage and incoming Stage are the same, the Forecast Category is not defaulted.
> If you are cloning an opportunity with products, the following events occur in order:
         1. The parent opportunity is saved according to the list of events shown above.
         2. The opportunity products are saved according to the list of events shown above.
Note
If errors occur on an opportunity product, you must return to the opportunity and fix the errors before cloning.
If any opportunity products contain unique custom fields, you must null them out before cloning the opportunity.

> Trigger.old contains a version of the objects before the specific update that fired the trigger. However, there is an exception. When a record is updated and subsequently triggers a workflow rule field update, Trigger.old in the last update trigger won’t contain the version of the object immediately prior to the workflow update, but the object before the initial update was made. For example, suppose an existing record has a number field with an initial value of 1. A user updates this field to 10, and a workflow rule field update fires and increments it to 11. In the update trigger that fires after the workflow field update, the field value of the object obtained from Trigger.old is the original value of 1, rather than 10, as would typically be the case.

No comments:

Post a Comment

Lightning Inter-Component Communication Patterns

Lightning Inter-Component Communication Patterns If you’re comfortable with how a Lightning Component works and want to build producti...