top of page

Updated: Dec 20, 2021

Apex Triggers execute before or after a database insert, update, delete, merge, upsert, undelete, or any combination thereof. Salesforce.com allows Triggers for most standard and all custom objects if running Unlimited, Developer, Enterprise, or Database.com editions of Salesforce.com.

Apex Triggers allow developers to programmatically check for duplicate records, update fields across objects, automate the creation of new records based on criteria, and much more. For example, if I wanted to check for duplicity on the user email field every time a user was created or updated I would write a trigger and assign the "before insert, before update" operations to it. This would allow me to query the database and throw an exception if a duplicate is found before saving to the database.


Trigger:


trigger triggerName on Object( operation/s ) {
/* -- Execute Trigger Logic Here -- */
}


Governor Limits

Salesforce.com is a multi-tenant environment. In an effort not to jeopardize the availability of shared resources, Salesforce.com enforces governor limits which will return a runtime exception and the code executing will fail. For details on all Salesforce.com governor limits refer to Winter 12' Governor Limits Quick Reference Guide.

Apex Governor Limits

Apex Triggers are bound by the Apex governor limits. As of Salesforce.com's Winter 12 Release they are as follows:

DescriptionLimitTotal number of SOQL queries issued100Total number of SOQL queries issued for Batch Apex and future methods200Total number of records retrieved by SOQL queries50,000Total number of SOSL queries issued20Total number of records retrieved by a single SOSL query200Total number of DML statements issued150Total number of records processed as a result of DML statements, Approval.process, or database.emptyRecycleBin10,000Total number of executed code statements200,000Total number of executed code statements for Batch Apex and future methods1,000,000Total heap size3 MBTotal heap size for Batch Apex and future methods6 MBTotal stack depth for any Apex invocation that recursively fires triggers due to insert,update, or delete statements16For loop list batch size200Total number of callouts (HTTP requests or Web services calls) in a request10Maximum timeout for all callouts (HTTP requests or Web services calls) in a request120 secondsDefault timeout of callouts (HTTP requests or Web services calls) in a request10 secondsTotal number of methods with the future annotation allowed per Apex invocation10Maximum size of callout request or response (HTTP request or Web services call)3 MBTotal number of sendEmail methods allowed10Total number of describes allowed100Total number of test classes that can be queued per a 24–hour periodThe greater of 500 or 10 multiplied by the number of test classes in the organization


Best Practices

The Force.com platform provides developers the flexibility to write and easily deploy Apex Triggers. Apex Triggers, like any powerful tool, need to be written with solid logic and thoroughly tested before deploying into a production environment.

  • Use one Apex Trigger for every object; all logic should be handled by an external Apex Class.

  • Keep Apex Trigger logic simple, and thoroughly documented with code comments.

  • Write Test Classes that execute the code in realistic scenarios.

  • Write Apex Triggers for bulk processing (up to 200) records at a time.

  • DML statements should execute on collections not individual records.

  • Add field validations on both the before and after operations.

  • Use static variables to persist on both the before and after operations.

  • Do not execute SOQL queries inside for loops, or inside of any before or after operations.

Design Pattern

Utilize consistent design patterns for Apex Triggers as you would any other code and the code will be more likely to run efficiently, within governor limits, and bug-free.

Example Trigger

An Apex Trigger should be written so that every operation calls a method in an external Apex Class. By doing so code can easily be added or removed, and variables can be used multiple times without additional queries to the database.


Trigger


trigger objectTrigger on Object (after delete, after insert, after undelete, after update, before delete, before insert, before update) {


  objectTriggerHandler handler = new objectHandler();


  /* Before Insert */
  if(Trigger.isInsert && Trigger.isBefore){
    handler.OnBeforeInsert(Trigger.new);
  }
  /* After Insert */
  else if(Trigger.isInsert && Trigger.isAfter){
    handler.OnAfterInsert(Trigger.new);
  }
  /* Before Update */
  else if(Trigger.isUpdate && Trigger.isBefore){
    handler.OnBeforeUpdate(Trigger.old, Trigger.new, Trigger.newMap);
  }
  /* After Update */
  else if(Trigger.isUpdate && Trigger.isAfter){
    handler.OnAfterUpdate(Trigger.old, Trigger.new, Trigger.newMap);
  }
  /* Before Delete */
  else if(Trigger.isDelete && Trigger.isBefore){
    handler.OnBeforeDelete(Trigger.old, Trigger.oldMap);
  }
  /* After Delete */
  else if(Trigger.isDelete && Trigger.isAfter){
    handler.OnAfterDelete(Trigger.old, Trigger.oldMap);
  }


  /* After Undelete */
  else if(Trigger.isUnDelete){
    handler.OnUndelete(Trigger.new);
  }


}



Example Trigger Handler Class

The Apex Trigger template above calls a handler class to execute the trigger logic, the trigger handler class should be defined as follows:

Apex


public with sharing class ObjectTriggerHandler {


  private boolean m_isExecuting = false;


  public ObjectTriggerHandler(boolean isExecuting){
    m_isExecuting = isExecuting;
  }


  public void OnBeforeInsert(Object[] newObjects){
    // EXECUTE BEFORE INSERT LOGIC
  }


  public void OnAfterInsert(Object[] newObjects){
    // EXECUTE AFTER INSERT LOGIC
  }


  public void OnBeforeUpdate(Object[] oldObjects, Object[] updatedObjects, MapObjectMap){
    // BEFORE UPDATE LOGIC
  }


  public void OnAfterUpdate(Object[] oldObjects, Object[] updatedObjects, MapObjectMap){
    // AFTER UPDATE LOGIC
  }


  public void OnBeforeDelete(Object[] ObjectsToDelete, MapObjectMap){
    // BEFORE DELETE LOGIC
  }


  public void OnAfterDelete(Object[] deletedObjects, MapObjectMap){
    // AFTER DELETE LOGIC
  }


  public void OnUndelete(Object[] restoredObjects){
    // AFTER UNDELETE LOGIC
  }


  public boolean IsTriggerContext{
    get{ return m_isExecuting;}
  }
}



Recursive Triggers

Prevent Apex Triggers from running recursively and thus exceeding governor limits, include the following statement to the Apex Trigger handler class.

Apex


public static boolean firstRun = true;


Insert the following into the OnAfterUpdateMethod.
if (firstRun) {
  firstRun = false;
}
else {
  System.debug('Already ran!');
  return;
}


Many excellent contributions by experienced Salesforce.com developers made this article possible. Please use the references to their sites and related blog posts below for more information. Happy Coding!

Other Resources

  • Mike Leach: A Simple Trigger Template for Salesforce (2010/07/08)

  • Ray Dehler:Prevent an Apex Trigger from Executing Twice (2011/04/13)

  • Jeff Douglas: Force.com Programming Best Practices (2010/10/21)

  • Developer Force - Apex Code Best Practices


34 views0 comments

What are the different types of controllers?

Controller definition: A visual force controller is a set of instructions that specify what happens when a user interacts with the components specified in associated Visualforce markup, such as when a user clicks a button or a link.


Controllers also provide access to the data that should be displayed in a page, and can modify component behavior.


Standard Controller: A standard controller consists of the same functionality and logic that is used for a standard Salesforce page. For example, if we use the standard accounts controller, clicking a Save button in a Visualforce page result in the same behavior as clicking Save on a standard Account edit page.


Custom Controller: A custom controller is a class written in Apex that implements all of a page logic.

If we use custom controller, we can define new navigation elements or behaviors, but we must also reimplement any functionality that was already provided in a standard controller.


Controller Extensions: A controller extensions is a class written in Apex that adds to or overrides behavior in a standard or custom controller. Extensions allow us to leverage that functionality of another controller while adding our own custom logic.


4 views0 comments

What is the difference between a standard controller and a custom controller?

  • Standard controller in Apex, inherits all the standard object properties and standard button functionality directly. It contains the same functionality and logic that are used for standard Salesforce pages.


  • Custom controller is an Apex class that implements all of the logic for a page without leveraging a standard controller. Custom Controllers are associated with Visualforce pages through the controller attribute.


8 views0 comments
bottom of page