Search Here

Salesforce Interview Questions for Triggers

1. What is a Salesforce Trigger?

A Salesforce Trigger is a piece of Apex code that executes before or after specific data manipulation language (DML) events occur, such as before object records are inserted into the database, after records have been deleted, etc. Triggers are used to perform custom actions before or after changes to Salesforce records.

2. What is a Trigger Code?

A Trigger code in Salesforce is a piece of Apex code that automatically executes before or after specific data manipulation language (DML) events. These events include actions like insert, update, delete, and undelete on Salesforce records. The trigger code is used to perform custom logic, such as validation, automation, or modification of data, based on these DML events.

3. What are the Two Types of Triggers in Salesforce?

In Salesforce, there are two primary types of triggers:

  • Before Triggers: These are executed before the DML operation is completed on the database. They are typically used for validating or changing data before it is saved.
  • After Triggers: These triggers execute after the DML operation. They are used when you need to access field values that are set by the system (such as a record’s ID or LastModifiedDate field), or to make changes in other records based on the actions of the initial record.

4. What are the Best Practices for Triggers in Salesforce?

Some best practices for writing triggers in Salesforce include:

  • Bulkify Your Triggers: Ensure your trigger can handle multiple records at a time efficiently.
  • Avoid Recursive Triggers: Implement checks to prevent a trigger from calling itself and causing a loop.
  • Optimize Code: Minimize SOQL queries and DML statements, especially inside loops.
  • Use Context Variables Wisely: Leverage context variables like Trigger.new and Trigger.old appropriately.
  • Modular Code: Use handler classes to keep your trigger logic organized and maintainable.
  • Error Handling: Implement robust error handling within your triggers.

5. What is the Purpose of a Trigger in Salesforce?

The primary purpose of a trigger in Salesforce is to perform automated actions either before or after a data manipulation event in the Salesforce database. Triggers help enforce business logic, maintain data integrity, automate processes, and ensure data validation and consistency. They extend the functionality of Salesforce beyond its standard capabilities, allowing for customized behaviors and workflows tailored to specific business needs.

6. Can you explain the difference between before and after Triggers?

Before Triggers are used to update or validate record values before they’re saved to the database, whereas After Triggers are used to access field values that are set by the system and to affect changes in other records. The records that fire After Triggers are read-only.

7. How do you prevent recursive Triggers in Salesforce?

To prevent recursive Triggers in Salesforce, you can use a static variable. The static variable acts as a flag, which you can set in your Trigger. When the Trigger is called again due to recursion, you can bypass your logic based on the flag’s value.

8. What are governor limits in Salesforce, and how do they affect Triggers?

Governor limits in Salesforce are runtime limits enforced by the Apex runtime engine to ensure that code does not monopolize shared resources. If a trigger exceeds these limits, it is terminated and rolled back. Therefore, understanding and coding with these limits in mind is crucial to developing in the Salesforce environment.

9. What does it mean to bulkify a Trigger in Salesforce?

Bulkifying a Trigger in Salesforce means making sure the code properly handles more than one record at a time. When a batch of records initiates a DML operation, a single instance of the trigger is executed, so the Trigger needs to handle all records in that operation.

10. Can you discuss some best practices when writing Triggers?

Some best practices when writing Triggers include:

  • Always bulkify your Triggers to handle multiple records.
  • Use collections (List, Set, Map) to store data.
  • Avoid SOQL or DML statements inside FOR loops.
  • Avoid hard-coding IDs.
  • Use Trigger context variables.
  • Write test classes for Triggers covering positive and negative scenarios
  • Modularize your code by using helper classes.

11. How do you test Triggers in Salesforce?

To test Triggers in Salesforce, you write test classes and methods. In the test methods, you create test data and perform DML operations that invoke the Trigger. You also use System.assert methods to verify the Trigger’s behavior.

12. How can you call a batch class from a Trigger?

While it’s not recommended due to potential governor limit issues, you can call a batch class from a Trigger using the Database.executeBatch method. A better practice is to use a queueable or future method to handle asynchronous processing.

13. When would you use a Trigger instead of Workflow, Process Builder, or Flows?

You would use a Trigger instead of Workflow, Process Builder, or Flows when dealing with complex business logic that cannot be handled by these declarative tools or when you need to create or manipulate records related to the one being processed.

14. What is trigger.new and trigger.old in Salesforce?

In Salesforce, Trigger.new is a list of records that are being inserted or updated. For an insert operation, Trigger.new contains all new records. For an update operation, it contains new versions of the records.

Trigger.old provides the old version of records before they were updated, or the records that have been deleted. It can be used in update and delete triggers to compare the state of the records before and after the DML operation.

15. What are context variables in Salesforce Triggers?

Context variables in Salesforce Triggers are variables that provide information about the runtime context of the Trigger, including the old and new versions of the records, which operations caused the Trigger to fire, and whether it was fired before or after the record was saved. Examples of context variables include Trigger.new, Trigger.old, Trigger.operationType, and so forth.

16. Can you write a Trigger to prevent the deletion of a record in Salesforce?

Yes. To prevent the deletion of a record, you can write a ‘before delete’ Trigger and add an error message to the record. When an error is added to a record in a ‘before’ Trigger, the transaction is rolled back, and the deletion does not occur.

17. How can you handle exceptions in Salesforce Triggers?

Exceptions in Salesforce Triggers can be handled using try-catch blocks. In the try block, you write the code which might throw an exception, and in the catch block, you handle the exception. This can involve adding an error message to the record or logging the error for review.

18. What is the purpose of the ‘Trigger.isExecuting’ context variable?

The Trigger.isExecuting context variable in Salesforce is used to determine whether the current context for the Apex code is a Trigger, not a Visualforce page, a Web service, or an executeanonymous() API call.

19. How would you stop a Trigger from executing multiple times?

To stop a Trigger from executing multiple times, you can use static variables. A static variable can act as a flag, which can be set after a Trigger executes. Then, on subsequent recursive calls to the Trigger, you can bypass the Trigger logic based on the flag’s value.

20. Can you explain the concept of a Trigger framework? Why is it used?

A Trigger framework is an architectural pattern in Apex which enables developers to manage their Trigger logic in a more modular and maintainable way. It often involves creating handler classes that contain the logic for each Trigger, and then a dispatching Trigger which calls the appropriate handler. The Trigger framework is used to reduce code duplication, improve code reuse, and enhance maintainability.

21. How do you ensure that your Triggers are bulk-safe?

To ensure that Triggers are bulk-safe, you must avoid DML operations or SOQL queries inside loops, which can quickly hit governor limits when dealing with multiple records. Instead, you should collect records or data in collections (like Lists or Maps), and then perform the operations on those collections outside of loops.

22. How would you write a Trigger to count the number of tasks associated with an account?

You can write an ‘after insert’, ‘after update’, and ‘after delete’ Trigger on the Task object. Within this Trigger, count the number of Tasks related to each Account. Then, update a custom field on the Account object with this count. Note that this is a simple example and in a production scenario you would want to handle potential exceptions and bulkify the operation to cater for multiple task updates.

Here is a simple example of such a Trigger:

Copy code

trigger TaskCountTrigger on Task (after insert, after update, after delete, after undelete) {
Set<Id> accountIds = new Set<Id>();
List<Account> accountsToUpdate = new List<Account>();

if(Trigger.isInsert || Trigger.isUpdate || Trigger.isUndelete){
for(Task t : Trigger.new){
accountIds.add(t.WhatId);
}
}

if(Trigger.isUpdate || Trigger.isDelete){
for(Task t : Trigger.old){
accountIds.add(t.WhatId);
}
}

for(AggregateResult ar : [SELECT WhatId, COUNT(Id) taskCount
FROM Task
WHERE WhatId IN :accountIds
GROUP BY WhatId]){
accountsToUpdate.add(new Account(Id=(Id)ar.get(‘WhatId’), Tasks_Count__c=(Integer)ar.get(‘taskCount’)));
}

update accountsToUpdate;
}

In this Trigger, Tasks_Count__c is a custom field on the Account object that stores the number of related Tasks. Note that the ‘WhatId’ field on the Task object is a polymorphic field that could relate to multiple objects, not just Account, so in a real-world scenario, you would need to handle this. Also, this Trigger doesn’t handle bulk operations very well and would hit governor limits if more than 10,000 Tasks related to a single Account were inserted at once. It’s important to consider these factors when designing Triggers.

23. When should you use Apex Triggers instead of Salesforce’s point-and-click functionality?

You should use Apex Triggers when the business logic cannot be achieved using Salesforce’s point-and-click functionality, like Workflow, Process Builder, or Flows. This may be due to complexity, the need for logic that spans multiple objects, or a requirement for more control than the declarative tools offer.

24. What is the purpose of a Trigger handler class?

The purpose of a Trigger handler class is to separate the logic of your Trigger from the Trigger itself. This separation leads to code that is easier to maintain and test. The handler class contains the methods that carry out the operations needed when the Trigger fires.

25. How would you write a test class for a Trigger?

To write a test class for a Trigger, you’ll need to write test methods that create the data needed for the Trigger to fire, perform the DML operation to fire the Trigger, and then use System.assert methods to verify that the Trigger had the expected effects. Salesforce requires at least 75% code coverage to deploy Triggers to production.

26. What are the best practices for writing efficient Salesforce Triggers?

Some best practices for writing efficient Salesforce Triggers are:

  • Bulkify your Trigger to handle multiple records at a time.
  • Minimize SOQL and DML operations, especially inside loops.
  • Use collections like Lists, Sets, and Maps to store data.
  • Use Trigger context variables effectively.
  • Avoid hardcoding IDs.
  • Use a Trigger framework to separate the Trigger logic from the Trigger itself.
  • Write comprehensive test classes to ensure your Trigger works as expected.

27. What happens if a Trigger causes a runtime exception?

If a Trigger causes a runtime exception, the entire transaction is rolled back. This includes all DML operations and changes in governor limit usage.

28. What are the limitations of using Triggers in Salesforce?

Triggers in Salesforce are subject to several limitations:

  • Triggers are not suitable for time-consuming operations as they can hit governor limits.
  • They can lead to recursion if not handled properly.
  • Triggers run on all records of a batch operation, so selective processing can be challenging.
  • Debugging Triggers can be difficult, particularly in production.
  • Overutilization of Triggers can lead to complex order of execution scenarios.

29. How do you debug a Trigger in Salesforce?

To debug a Trigger in Salesforce, you can use debug logs. You can add System.debug statements in your Trigger code, and then check the logs after executing the operations that fire the Trigger.

30. Can you explain how to write an ‘after update’ Trigger in Salesforce?

An ‘after update’ Trigger in Salesforce is a Trigger that executes after a record is updated. Here is a simple example:

Copy code

trigger afterUpdateTrigger on Account(after update) {
for(Account a: Trigger.new){
// Your logic here
}
}

In this Trigger, you would replace “// Your logic here” with the code you want to execute after an Account is updated.

31. How would you use a static variable in a Trigger to prevent recursion?

You can use a static variable in a class, and check this variable in your Trigger. If the Trigger is fired due to a DML operation in the Trigger itself, you can bypass the Trigger logic. Here’s a simple example:

Copy code

public Class CheckRecursion{
public static Boolean alreadyRun = false;
}

trigger recursionTrigger on Account(after update) {
if(CheckRecursion.alreadyRun){
return;
}
CheckRecursion.alreadyRun = true;

// Your logic here
}

32. Can you have more than one Trigger for the same object?

Yes, you can have more than one Trigger for the same object in Salesforce. However, the order in which these Triggers are executed is not deterministic. Salesforce recommends having a single Trigger per object and using a Trigger handler class to separate and order the execution of your logic.

33. How can you disable a Trigger in Salesforce?

There isn’t a standard out-of-the-box way to disable a Trigger in Salesforce. However, there are several common strategies:

  • Commenting out the Trigger code and redeploying.
  • Using a custom setting that the Trigger checks before executing. If the custom setting is turned off, the Trigger will exit early.
  • If the Trigger is managed, you can deactivate it from the managed package’s settings.

Remember that in a production environment, changes to Triggers need to be made using a deployment process rather than directly in the production org.

Scenario based Interview Questions on triggers in Salesforce

Scenario 1: A company wants to prevent the deletion of Account records that have related Opportunities. How would you implement this using a trigger?

You can achieve this by writing a ‘before delete’ trigger on the Account object. The trigger would check for related Opportunities for each Account being deleted. If related Opportunities are found, the trigger would add an error to the Account record, preventing its deletion.

trigger PreventAccountDeletion on Account (before delete) {
List<Id> accountIds = new List<Id>();
for(Account acc : Trigger.old) {
accountIds.add(acc.Id);
}
Map<Id, AggregateResult> relatedOpps = new Map<Id, AggregateResult>(
[SELECT AccountId, COUNT(Id) oppCount FROM Opportunity WHERE AccountId IN :accountIds GROUP BY AccountId]
);
for(Account acc : Trigger.old) {
if(relatedOpps.containsKey(acc.Id) && (Integer)relatedOpps.get(acc.Id).get(‘oppCount’) > 0) {
acc.addError(‘Cannot delete Account with related Opportunities.’);
}
}
}

Scenario 2: You need to update a custom field on the Contact object, ‘LastCaseDate’, with the date of the most recent related Case. How would you write this trigger?

This would be an ‘after insert’ and ‘after update’ trigger on the Case object. The trigger would gather Contact IDs from the Cases, find the most recent Case date for each Contact, and update the ‘LastCaseDate’ field on the Contact records.

trigger UpdateLastCaseDate on Case (after insert, after update) {
Set<Id> contactIds = new Set<Id>();
for(Case cs : Trigger.new){
if(cs.ContactId != null){
contactIds.add(cs.ContactId);
}
}
Map<Id, Date> contactLastCaseDate = new Map<Id, Date>();
for(AggregateResult ar : [SELECT ContactId, MAX(CreatedDate) lastDate FROM Case WHERE ContactId IN :contactIds GROUP BY ContactId]){
contactLastCaseDate.put((Id)ar.get(‘ContactId’), (Date)ar.get(‘lastDate’));
}
List<Contact> contactsToUpdate = new List<Contact>();
for(Id contactId : contactIds){
contactsToUpdate.add(new Contact(Id = contactId, LastCaseDate__c = contactLastCaseDate.get(contactId)));
}
update contactsToUpdate;
}

Scenario 3: A sales team wants to ensure that no Opportunity is created with a closing date in the past. How would you enforce this with a trigger?

You would use a ‘before insert’ and ‘before update’ trigger on the Opportunity object. The trigger would check the ‘CloseDate’ of each Opportunity record, and if the date is in the past, it would add an error message to the record.

trigger ValidateOpportunityCloseDate on Opportunity (before insert, before update) {
for(Opportunity opp : Trigger.new){
if(opp.CloseDate < Date.today()) {
opp.addError(‘Close Date cannot be in the past.’);
}
}
}

Scenario 4: When an Account’s status changes to ‘Inactive’, all related Opportunities should be marked as ‘Closed Lost’. How would you accomplish this?

This would be an ‘after update’ trigger on the Account object. The trigger checks if the status has changed to ‘Inactive’ and then updates the status of all related Opportunities to ‘Closed Lost’.

trigger CloseRelatedOpportunities on Account (after update) {
List<Opportunity> oppsToUpdate = new List<Opportunity>();
for(Account acc : Trigger.new){
if(acc.Status__c == ‘Inactive’ && (Trigger.oldMap.get(acc.Id).Status__c != ‘Inactive’)){
oppsToUpdate.addAll([SELECT Id FROM Opportunity WHERE AccountId = :acc.Id AND StageName != ‘Closed Lost’]);
}
}
for(Opportunity opp : oppsToUpdate){
opp.StageName = ‘Closed Lost’;
}
if(!oppsToUpdate.isEmpty()){
update oppsToUpdate;
}
}

Scenario 5: You need to ensure that a custom ‘Total Revenue’ field on Account is always the sum of all related Opportunities’ ‘Amount’ fields. How would you implement this?

This would involve writing an ‘after insert’, ‘after update’, and ‘after delete’ trigger on the Opportunity object. After any of these operations, the trigger would recalculate the total revenue for the related Account based on the sum of the Amount fields of its Opportunities and update the ‘Total Revenue’ field accordingly.

trigger UpdateAccountRevenue on Opportunity (after insert, after update, after delete, after undelete) {
Set<Id> accountIds = new Set<Id>();

// Collect Account IDs from the Opportunities in the trigger context
if(Trigger.isInsert || Trigger.isUpdate || Trigger.isUndelete){
for(Opportunity opp : Trigger.new){
accountIds.add(opp.AccountId);
}
}
if(Trigger.isUpdate || Trigger.isDelete){
for(Opportunity opp : Trigger.old){
accountIds.add(opp.AccountId);
}
}

// Aggregate the total revenue for each Account
Map<Id, Decimal> accountRevenues = new Map<Id, Decimal>();
for(AggregateResult ar : [SELECT AccountId, SUM(Amount) totalRevenue FROM Opportunity WHERE AccountId IN :accountIds AND IsClosed = false AND IsWon = true GROUP BY AccountId]){
accountRevenues.put((Id)ar.get(‘AccountId’), (Decimal)ar.get(‘totalRevenue’));
}

// Update the Accounts with the new Total Revenue
List<Account> accountsToUpdate = new List<Account>();
for(Id accId : accountIds){
accountsToUpdate.add(new Account(Id = accId, Total_Revenue__c = accountRevenues.get(accId)));
}
update accountsToUpdate;
}

In this scenario, the trigger ensures that every time an Opportunity is created, updated, deleted, or undeleted, the ‘Total Revenue’ on the related Account is recalculated to reflect the current sum of all related Opportunities’ ‘Amount’ fields. This maintains accurate financial data on the Account record in real-time.




Post a Comment

0 Comments
* Please Don't Spam Here. All the Comments are Reviewed by Admin.