CRT-450 Salesforce Certified Platform Developer – Process Automation and Logic – 38% Part 2
- 3.9- Apex Triggers Pattern for Efficient Data Processing
In the previous lecture, we have talked about triggers, about how to design them, where to write them, and when to use them. And then at the end of the previous lecture, we have shown you some examples of triggers. And then we have ran these triggers and we have tested them. In this lecture, we’ll talk about how to design Apex triggers for effective data processing. What to avoid when a trigger and what are the trigger best practices. There are many concepts that you need to avoid when designing and trigger. First of all, you have to stop assuming that only one record will be affected. So most of the time it will be one record that is entered through the GUI.
But sometimes it can be more than one record. So let’s say you are using the data loader to load some data. So in this case, it will be much more than one record at a time triggering a trigger. Second, you need to stop running Socalled query inside the triggers for loop. And finally, you need to stop running DML statements inside the triggers for loop. Let’s start by the first do not you should not assume that only one record will be affected. A common development pitfall is the assumption that only one record will enter a trigger.
So you assume that most of the time you are using the GUI, and most of the time one record only will trigger a trigger. But this is not the case. As we have talked earlier on, if you are loading data through the data loader, much more than one record will be affected. In fact, a trigger that knew the list of S object can have as many as 200 records at a time, and up to 200 records can enter your trigger at a time. Your trigger should be designed to handle this. It should not be designed to handle only one record at a time. And to do that, we have to make sure that we invoke the context variable that we have talked about in the previous lecture. Now the second do not you should not run any Socalled query inside any for loop and a trigger. As you recall, Salesforce is multitenant, which means that you are sharing your instance with many other organizations.
This is why Salesforce has something called Governor limits. We’ll see these in detail in a later lecture. But for now, one of the Governor limits imposed by Salesforce is the number of times that you can invoke a sock will query within a single transaction. And this number is set to 100. So you cannot invoke more than 100 sock will query at a time. And if you exceed these 100 sockwell queries, you will get an exception. The exception is too many the exception is too many Socalled queries and you will fail to execute your query. The solution is to run any SoCal outside any for loop in a trigger and to save it in a list and then you can iterate through the list using a for each loop. The third do not is that you should not run any DML statements inside any for loop in a trigger. Another governor limit imposed by Salesforce is the number of DML statements that you can issue at one time within a single transaction and this number is set to 150.
So you cannot have more than 150 DML statements at a time with salesforce. If you exceed these 150 DML statements, you will get an exception and your trigger will fail to execute. What’s the solution? The solution is to save the result inside a list and then you can issue one DML statement on this list. So in this case, you will not issue many DML statement on each as record. You will save these as records in a list and then you will issue a single DML statement on the whole list. Also, one thing to be aware of is cascading triggers. When your trigger modify records, this may cause other triggers to fire, for example with roll up summary fields and if the charge record is modified, then this will cause the roll up summary field to be modified and which may cause another trigger to run and so on. So a single trigger can execute other triggers based on the records that it changes.
So triggers are not run all alone by themselves, so they are not a closed entity. If a trigger runs, it might cause other triggers to run based on the changes that they have made. All these triggers, the first one and the consequent ones are considered as part of one transaction, of one execution. So you have to make sure that this whole execution is under the governor limit that we have talked about earlier on. There are many best practices that we need to consider when designing a trigger. First of all, we have to write logic left triggers and we need to let the trigger use hangary classes. This means that the trigger should not have any code, it should only point to other methods, any classes, and the whole code should be in these classes. The second thing that we have to take care of is to write only one trigger per object. So instead of writing three, four, five and so on triggers per one object, we have to make sure to write only one trigger per object.
And this trigger should use context specific handler methods. So the trigger will have many events, it will have all the events that can run on this trigger and then it will have many if statements inside. And using the if statement we can specify, for example, if the event is before update, do this. If the event is after update, do that. So in this case, we can have one trigger for one object and this trigger will have all the different events and we can specify which actions were run. We can specify which handler class methods to call based on the event. First of all, let’s start with the first do we need to have logic class triggers? And instead we have to use a hand recluses to handle the code. The role of the trigger is just to delegate the logic of responsibilities to some other handwrite class.
So the trigger will only point to other class methods and the whole code will be inside these methods. Why? Testing a trigger is very difficult. If all the application logic is inside the trigger itself, we need to go to the trigger and we need to trace it and we need to build test classes to follow up on these lines of code. You also cannot expose logic to be reused anywhere else in your. So if we have the code within a trigger, this code belongs to the trigger and we cannot use this code again in another trigger, which is not a good thing to do.
And finally, writing your code inside the trigger and then adding code day after day will make this trigger a mass and it will be very hard to follow. To solve this, we create something called handler class and we let the trigger call the different methods of this class. Let me give you an example. Let’s say you have a trigger on the account object. This trigger will be called account trigger. And then the handler class that this trigger will use will be called account trigger handler. This class will have all the method that any account trigger will use and the account trigger will point to these different methods. Now to the second. Do we have to have one trigger per every object? We cannot have more than one trigger. This is a best practice. Of course you can have more than one, no one will stop you. But as a best practice, we need to get only one trigger per object. With multiple triggers per one single object, you have no way of controlling the order of execution.
So if you have different triggers that will fire before inserting, you cannot control which trigger will run first. For that, a single apex trigger is all you need for any particular object. And a single trigger can handle all the possible combinations. So as we have mentioned earlier on, we have one trigger and this trigger will have all the events it can have before update, before insert, before delete, after update, after insert, after delete, and after undelete. And then in the body of this, we have different methods. For every event we will have a method. So we’ll have in this case one trigger per one object. And all the methods that this trigger will call will be inside this trigger. We will not have any other code,
we will not have any lines of code. We’ll only have methods that are called this is what we are talking about. And this is also another. Do we need to create context specific handler class methods inside the trigger handler class. So inside one class, we have to create different methods and different contexts. So each one of these methods will be linked to one context. So let’s say one method will run during the before insert. So in this case, we add this method to the handler class. And in the trigger, we call this method after the if statement. So as you can see, in this example, we have a trigger. And this trigger has two events and it has an if statement. So if the event is after insert, called this method from the handler class. So inside the handler class, we have different methods. You can see the name of the method Handle after insert. And we don’t have any code here, we just have a method calling and the whole code will be inside the handler class. And also, another do is to use maps instead of lists inside a trigger. A trigger can have more than one contact variable.
So it’s better to use maps instead of lists and a trigger. Why? Because maps will have IDs and will have records. So in this case, we’ll have access to both IDs and records instead of only records. This is an example. As you can recall from the previous lecture, we had more than one trigger on the account object. We had this first trigger, which is called Hello World Trigger, and it will fire before insertion. And we also had this second one, which is called Task Trigger, and it will fire after insertion. Now, when we tested these, they did work just fine, but there are some issues. First of all, if you notice here, there is a full loop, and inside this for loop, we can see a DML statement. Now, what if we have 200 records here? In this case, this for loop will loop 200 times, and this will pass the governor limit of DML and this will fail. So this is not a good design. Let’s see how we can solve this. Now, how can we solve this? To solve this, we need to first create a class, a handler class called account trigger handler. And inside this class, we create as many methods as we want.
So the first method will be called handle before insert, and it will contain any code that we want executed before insertion. So in this case, let me go back. We have two triggers, and before insertion, we only have this code. So I will take this code and I will put it inside this method. So now whenever I call this method, this action will be performed. So let me go back to the other method. The other method will do this, so let me do the same. I will create a method called handle after insert and it will take a list of account as an argument, just like the first one. And then it will have the code. But notice here we had the DML statement inside the for loop, which is not a good practice. What we did here, we created a list of tasks called My tasks. And then we have added any new task to this list. And then outside the full loop, we are using the DML statement to insert the whole list. So this exactly will do same as this but it will not have any DML statement inside the for loop.
Now to the trigger, the trigger will be called account trigger and the trigger will have all the events and then by using if statements on context variables we can pinpoint the events so in this case it will be a trigger is before and a trigger is inserted so in this case it will be a before insert. So in that case we have to call this method and this method is exactly that one here. So in this case calling this will execute this code. I’d notice that this method is static which means that I don’t need to instantiate this class and same thing for the other events. So in the case of after insert call that method which is this one here in the future and if you want to add any new code we don’t touch this, we keep this the same. We only go to the class and we add our code here and if we need to add more events we can add another method and we can add the code of the event and start this method and we can also add it here and we can add another if statement. Let’s now go to salesforce and let’s fix our triggers.
- 3.9- Apex Triggers Pattern for Efficient Data Processing – Demo
Let’s first go to the setup menu and let’s click on the triggers link. We go to develop and apex triggers. And let’s see what triggers we have. We have, until now, four triggers on the account records. And each one of these will do something. Let’s now create a class, a handler class for this account object. And then let’s create one trigger that will take care of calling different methods on this class. So I will go to the developer console. So on the developer console, let me open first all the triggers. So file open triggers. So this is the first one and then we’ll do the same for the rest. And now let’s create a class. So this class will be the handler class. It will be called Account Director Handler. Now in this class, let’s create different methods based on the different events. So the first method will be called a Handle Before Insert, and it will have this code and that code. So let’s create this method and it will take a list of accounts. So now what we have to put, what code we have to put here, we have to put the code that is now present in each one of these.
So this is the first action that we want. And then we also want this action. But notice that this trigger, it does not have any context variable, so it will only act on one record. So to fix this, we need to put it inside a for loop. So let’s first copy this and let’s paste it here. Now we have a for loop. This for loop will loop into each one of the account records. In this case, it will not be triggered as new. It will be the argument. So it will be acclist. So this will be taken from the argument that we will provide. And this for loop will loop into each one of the records of this list. And what it will do, it will first add this string into the description field of the account. And let me copy this and let me paste it here. Control a shift tab. So what we have now, we have a method called Handle Before Insert that has all the codes of both triggers and that has a for loop, which means that it will take care of the many records that will enter this trigger.
Now the third trigger is that one, and this will be fired after installation. So let’s go ahead and create another method, control A and Shift tab. And then let’s call this handle after insert. And this will also take a list of accounts. Let me remove the code and let’s fix this trigger. First of all, as we have mentioned, there’s a fault here. The fault is that we have a DML statement inside the for loop. How to fix this, we have to create a task, a list of tasks, and then we have to insert this task into this list and then outside the for loop we will call the DMR statement. So let’s do this, let’s create a task list before the for loop. So it will be a list of tasks and then let me copy and paste to fix the code. And then inside the for loop we have a new task. We are creating a new task and we are doing the same thing and the trigger.
But in this case what we’ll do at the end, we will add this A task to the list. So my task that add and the argument will be the A task and then outside the for loop we will use the DIY statement insert to insert the whole list. So what we did until now, we have created a class called account trigger handler that will be used to host all the trigger score. And inside we have created two methods. One is called handle before insert. It will take a list of account as an argument and the other is called a handle after insert. And both of these are static which means that I don’t need to instantiate the class, I can call them directly from the class itself. And each one of these will contain the whole lines of code of the triggers. And in this case I don’t need to create different triggers, I just have the code here and then the trigger will only be used to call these methods. So now let me try to click on Save or Control us. I have an error.
Let’s see the error. So it’s on line number nine. So I missed this control us, same thing online numbers and now we’re good. So this is the class. Now let’s go and create a trigger file new apex trigger and this will be called Account trigger and it will be on the Account object. And the whole job of this trigger is to call the methods of this by using the context variable if statements. So if trigger. So if this is the case, so if the trigger is a before trigger and is an insert trigger, what we should do, we should call this method. So let me copy the class name and argument will be what it will be the trigger new. So let’s do the same for the other event. So. Alice so now, in this case, if the trigger is an after trigger and it is an insert trigger called the method that is called handle after insert. And the argument will be the same control a control s now, we can get rid of these.
I don’t need them anymore because I have their code in the class. So to do that, just click the trigger itself and type control plus delete. Now let’s go to salesforce and let us test this. So let me go to the Account object and new account. So this will be called test account three. So now what should happen whenever I click on save. This trigger will be calling this method before saving and this method after saving. And this method is what it is. That one. And this one is what? This one. Let’s see what happened. So what happened? Now we have a new account called Test Account Three. And as you can see, we have the description set. And also if I go to the developer console, I can see the log. Let me open the log and let’s see that the hello world was added. There you go. But there’s one thing, if you can guess what it is. Let me go to the trigger and let’s see what is the issue. So read the first line and let’s go back to the Test account tree.
Now, if I go down, I could not see any task even though I have here this. But why? It was not executed well, because I did not specify after insert here I just have the default event. So what I need to do, I need to add after insert control us. So now let me test this again account. And let’s create a new account called Test Account Four. Save. Now we should have the same thing, but we should have the task. There you go. Why the Task was not created with test account three. Because I missed this and the events of the trigger, I had to add it because by default, the developer console will only add the before insert. I have to add any other events that I want. So this was the Apex triggers pattern for efficient data processing lecture. In this lecture, we have seen what we need to avoid when designing a trigger. We need to stop assuming that only one record will be affected in a trigger.
We need to stop running any sockwell queries inside the full loop of a trigger. And we need to stop running any DML statements inside the for loop of a trigger. And also we need to follow these best practices. First of all, we need to write our triggers without any code. We need to write only one trigger per object. And we need to use context specific handler methods inside the handler classes. And finally, we need to use maps instead of lists. And finally, beware the cascading triggers. A trigger can cause another trigger to run and this will affect the governor limits. And finally, as usual, thanks for watching.
- 3.10- Governor Limits
Hey guys. This is section three logic and Process Automation. And this is lecture number 13 governor limits. As we have seen in the previous lecture, we need to avoid many design patterns when building a trigger. One of these is to avoid having a sockwell query instead for loop and the other is to avoid having a DML statement and for loop. Why? Because we have mentioned Salesforce has something called Governor limits. These are some limits imposed by Salesforce because it’s a multitenant environment. For example, we cannot have more than 100 Socalled query cold in one transaction and we cannot have more than 150 DML statement called in one transaction. And this lecture will talk in detail about these, why they are imposed by salesforce, what are they? And also we’ll jump into Salesforce and I will show you these in action. As we have mentioned before, Salesforce runs in a multitenant environment which means that you are sharing one Salesforce instance with many other organizations which means that you are sharing the resources of this instance like the CPU power, like Ram, like bandwidth and so on. As a result, and to protect the instance resources, salesforce has implemented resources usage limits. These are called government limits.
Let’s see these and let’s see what are they? First of all, we talk about the per transaction limit. A transaction is just one execution of your Apex code. First thing we’ll talk about is the number of sockwell queries that can be issued in one transaction which is in this case, 102 hundred. In the case of Async, the total number of records that are retrieved by a sock will query can be maximum 50,000 records. So if you have one Socalled query issued but the result of this sock will query is more than 50,000 records, you will get an error. The total number of DML statements that can be issued in one transaction is 150 and the records that can be processed as a result of a DML statement is maximum 10,000. The total number of SOSL queries that can be issued is 20 and the number of records that can be retrieved by a single SOSL query is 2000. The limits in red are the most important ones. You need to make sure not to forget how many Socalled queries you can issue in one transaction and how many records that can be received by a Socalled query or by Socalled queries in one transaction. And also you need to know how many DML statements can be issued in one transaction and what’s the maximum result that you can obtain from DML statements in one transaction. There are also other limits per transaction. Let me give you some examples.
The maximum adapt that triggers can be fired recursively is 16. So if a trigger fires another trigger and so on, the maximum will be 16. The total numbers of call outs, for example for Http requests or for web services calls is 100 for one transaction. The maximum time out for all call out is 120 seconds. And the maximum number of methods with the future annotation is 50. And you can also check the others here. These are also some other limits per transaction. We have the total heap size. It can be maximum six MB and the twelve MB for async the maximum CPU time on the salesforce server. So as we have mentioned, you are sharing the instance with many other orgs. So you have a maximum CPU time. In this case it will be 10,000 milliseconds per one transaction.
The maximum execution time for each Apex transaction is ten minutes. So if you exceed this, the transaction will fail. The maximum number of push notification method calls allowed for one Apex transaction is ten. And the maximum number of push notification that can be sent in each push notification method call is 2000. Now, the second thing that we talk about is the certified managed package tour transaction limit. So these are packages that you install in your salesforce. org. These also have sublimits. The total number of Socalled queries that can be issued is 1100. Of DML statement that can be issued is 1650 and SOSL statement that can be issued is 220. Of course, a managed app is an application that you install through the App Exchange and that is controlled by the source. These apps have passed the security review by salesforce and that’s why they are published on the App Exchange. And these apps are developed by salesforce partners and they have their own namespace. And then we’ll talk about the force platform Apex limits. Of course, the force platform has some limits. For example, the maximum number of Apex classes that can be scheduled at the same time is 100. The maximum number of batch Apex jobs that can be queued at the same time is five. The maximum number of batch Apex job start method concurrent executions is just one.
And finally, the maximum number of batch jobs that can be submitted and a running test is five. These limits are not per one transaction, but they are imposed by the whole force platform. Now we’ll talk about the static Apex limits. We have also some limits on the static Apex. For example, the default timeout of call out Http requests of web services 10 seconds. The maximum so called query runtime before salesforce canceled, the transaction is 120 and so on. There are also some size specific Apex limits. For example, we can have a maximum of 1 million characters in one Apex class. And we can have also a maximum of 1 million characters and one Apex trigger and a maximum of three. And the total size of code and the whole salesforce also has limits on email. For example, the maximum number of email messages that are processed is dependent on the number of licenses that you have.
You need to multiply this number by 1000 and the maximum is 1 million. So it cannot be more than 1 million the maximum size of an email message. So it’s the size of the body and the attachment is ten MB the same. But in this case, for an email to case emailed, the maximum attachment is 25 MB. And finally, for the same email to case, the maximum number of email messages that are processes depending on the number of user license. So you need to multiply this by 1000 and maximum is 1 million. Salesforce also has limits on push notification for the apps. For example, if the app is provided by Salesforce, it has a maximum of 50,000 notifications per application per day. If the application was developed by your company for internal employee use, the maximum will be 35,000. And finally, if the application was installed from the app exchange, the maximum is 5000. Now let’s into Salesforce and let me show you the most important governor limits and actions.