Unit 5
Unit 5
Unit 5
Apex Triggers
Apex triggers enable you to perform custom actions before or after events to records in Salesforce,
such as insertions, updates, or deletions. Just like database systems support triggers, Apex provides
trigger support for managing records.
Typically, you use triggers to perform operations based on specific conditions, to modify related
records or restrict certain operations from happening. You can use triggers to do anything you can
do in Apex, including executing SOQL and DML or calling custom Apex methods.
Use triggers to perform tasks that can’t be done by using the point-and-click tools in the Salesforce
user interface. For example, if validating a field value or updating a field on a record, use validation
rules and flows. Use Apex triggers if performance and scale is important, if your logic is too
complex for the point-and-click tools, or if you're executing CPU-intensive operations.
Trigger Syntax
The syntax of a trigger definition is different from a class definition’s syntax. A trigger definition
starts with the trigger keyword. It is then followed by the name of the trigger, the Salesforce object
that the trigger is associated with, and the conditions under which it fires. A trigger has the
following syntax:
trigger TriggerName on ObjectName (trigger_events) {
code_block
}
To execute a trigger before or after insert, update, delete, and undelete operations, specify multiple
trigger events in a comma-separated list. The events you can specify are:
• before insert
• before update
• before delete
• after insert
• after update
• after delete
• after undelete
Trigger Example
This simple trigger fires before you insert an account and writes a message to the debug log.
1. In the Developer Console, click File | New | Apex Trigger.
2. Enter HelloWorldTrigger for the trigger name, and then select Account for the sObject.
Click Submit. & Replace the default code with the following.
trigger HelloWorldTrigger on Account (before insert)
{
System.debug('Hello World!');
}
3. To save, press Ctrl+S.
4. To test the trigger, create an account.
a. Click Debug | Open Execute Anonymous Window.
b.In the new window, add the following and then click Execute.
c. Account a = new Account(Name='Test Trigger');
insert a;
5. In the debug log, find the Hello World! statement. The log also shows that the trigger has
been executed.
Types of 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 affect changes in other records. The records that fire the
after trigger are read-only.
Using Context Variables
To access the records that caused the trigger to fire, use context variables. For example,
Trigger.new contains all the records that were inserted in insert or update triggers. Trigger.old
provides the old version of sObjects before they were updated in update triggers, or a list of deleted
sObjects in delete triggers. Triggers can fire when one record is inserted, or when many records are
inserted in bulk via the API or Apex. Therefore, context variables, such as Trigger.new, can contain
only one record or multiple records. You can iterate over Trigger.new to get each individual
sObject.
This example is a modified version of the HelloWorldTrigger example trigger. It iterates over
The example uses a hypothetical endpoint URL for illustration purposes only. You can’t run this
example unless you change the endpoint to a valid URL and add a remote site in Salesforce for
your endpoint.
public class CalloutClass {
@future(callout=true)
public static void makeCallout() {
request.setEndPoint(endpoint);
// Send the HTTP request and get the response. HttpResponse response = new
HTTP().send(request);
}
This example shows the trigger that calls the method in the class to make a callout asynchronously.
trigger CalloutTrigger on Account (before insert, before update) {
CalloutClass.makeCallout();
}
Performing Bulk SOQL
SOQL queries can be powerful. You can retrieve related records and check a combination of
multiple conditions in one query. By using SOQL features, you can write less code and make fewer
queries to the database. Making fewer database queries helps you avoid hitting query limits, which
are 100 SOQL queries for synchronous Apex or 200 for asynchronous Apex.
The following example (SoqlTriggerBulk) shows a best practice for running SOQL queries.
• Meeting the code coverage requirements for deploying Apex to production or distributing
Apex to customers via packages
• High-quality apps delivered to the production org, which makes production users more
productive
• High-quality apps delivered to package subscribers, which increase your customers trust
return cs.setScale(2);
Repeat the previous steps to create the TemperatureConverterTest class. Add the following for this class.
@isTest
private class TemperatureConverterTest {
@isTest static void testWarmTemp() {
Decimal celsius = TemperatureConverter.FahrenheitToCelsius(70);
System.assertEquals(21.11,celsius);
}
@isTest static void testFreezingPoint() {
Decimal celsius = TemperatureConverter.FahrenheitToCelsius(32);
System.assertEquals(0,celsius);
}
@isTest static void testBoilingPoint() {
Decimal celsius = TemperatureConverter.FahrenheitToCelsius(212);
System.assertEquals(100,celsius,'Boiling point temperature is not expected.');
}
@isTest static void testNegativeTemp() {
Decimal celsius = TemperatureConverter.FahrenheitToCelsius(-10);
System.assertEquals(-23.33,celsius);
}
}
After you run tests, code coverage is automatically generated for the Apex classes and triggers in
the org. You can check the code coverage percentage in the Tests tab of the Developer Console. In
this example, the class you’ve tested, the TemperatureConverter class, has 100% coverage, as
shown in this image.
Create and Execute a Test Suite
A test suite is a collection of Apex test classes that you run together. For example, create a suite of
tests that you run every time you prepare for a deployment or Salesforce releases a new version. Set
up a test suite in the Developer Console to define a set of test classes that you execute together
regularly.
You now have two test classes in your org. These two classes aren’t related, but let’s pretend for
the moment that they are. Assume that there are situations when you want to run these two test
classes but don’t want to run all the tests in your org. Create a test suite that contains both classes,
and then execute the tests in the suite.
1. In the Developer Console, select Test | New Suite.
2. Enter TempConverterTaskUtilSuite for the suite name, and then click OK.
3. Select TaskUtilTest, hold down the Ctrl key, and then select TemperatureConverterTest.
4. To add the selected test classes to the suite.
click >.
5. Click Save.
6. Select Test | New Suite Run.
7. Select TempConverterTaskUtilSuite and then move TempConverterTaskUtilSuite to
the Selected Test Suites column.
8. Click Run Suites.
9. On the Tests tab, monitor the status of your tests as they’re running. Expand the test run, and
expand again until you see the list of individual tests that were run. Like in a run of individual test
methods, you can double-click method names to see detailed test results.
Asynchronous Apex
In a nutshell, asynchronous Apex is used to run processes in a separate thread, at a later time.
An asynchronous process is a process or function that executes a task "in the background" without
the user having to wait for the task to finish.
Here’s a real-world example. Let’s say you have a list of things to accomplish before your weekly
Dance Revolution practice. Your car is making a funny noise, you need a different color hair gel
and you have to pick up your uniform from your mom’s house. You could take your car to the
mechanic and wait until it is fixed before completing the rest of your list (synchronous processing),
or you could leave it there and get your other things done, and have the shop call you when it’s
fixed (asynchronous processing). If you want to be home in time to iron your spandex before
practice, asynchronous processing allows you to get more stuff done in the same amount of time
without the needless waiting.
You’ll typically use Asynchronous Apex for callouts to external systems, operations that require
higher limits, and code that needs to run at a certain time. The key benefits of asynchronous
processing include:
User efficiency
Let's say you have a process that makes many calculations on a custom object whenever an
Opportunity is created. The time needed to execute these calculations could range from a minor
annoyance to a productivity blocker for the user. Since these calculations don't affect what the user
is currently doing, making them wait for a long running process is not an efficient use of their time.
With asynchronous processing the user can get on with their work, the processing can be done in
the background and the user can see the results at their convenience.
Scalability
By allowing some features of the platform to execute when resources become available at some
point in the future, resources can be managed and scaled quickly. This allows the platform to
handle more jobs using parallel processing.
Higher Limits
Asynchronous processes are started in a new thread, with higher governor and execution
limits. And to be honest, doesn’t everyone want higher governor and execution limits.
Future Run in their own thread, and do not start until resources Web service callout.
Methods are available.
Batch Apex Run large jobs that would exceed normal processing Data cleansing or archiving of records.
limits.
It’s important to note that future methods are not guaranteed to execute in the same order as they
are called. We'll say it again, because it's crucial for you to remember: future methods are not
guaranteed to execute in the same order as they are called. When using future methods, it’s also
possible that two future methods could run concurrently, which could result in record locking and a
nasty runtime error if the two methods were updating the same record.
Batch Apex
Batch Apex is used to run large jobs (think thousands or millions of records!) that would exceed
normal processing limits. Using Batch Apex, you can process records asynchronously in batches
(hence the name, “Batch Apex”) to stay within platform limits. If you have a lot of records to
process, for example, data cleansing or archiving, Batch Apex is probably your best solution.
Here’s how Batch Apex works under the hood. Let’s say you want to process 1 million records
using Batch Apex. The execution logic of the batch class is called once for each batch of records
you are processing. Each time you invoke a batch class, the job is placed on the Apex job queue
and is executed as a discrete transaction. This functionality has two awesome advantages:
• Every transaction starts with a new set of governor limits, making it easier to ensure that
your code stays within the governor execution limits.
• If one batch fails to process successfully, all other successful batch transactions aren’t rolled
back.
Batch Apex Syntax
To write a Batch Apex class, your class must implement the Database.Batchable interface and
include the following three methods:
start
Used to collect the records or objects to be passed to the interface method execute for processing.
This method is called once at the beginning of a Batch Apex job and returns either a
Database.QueryLocator object or an Iterable that contains the records or objects passed to the job.
Most of the time a QueryLocator does the trick with a simple SOQL query to generate the scope of
objects in the batch job.
execute
Performs the actual processing for each chunk or “batch” of data passed to the method. The default
batch size is 200 records. Batches of records are not guaranteed to execute in the order they are
received from the start method.
This method takes the following:
• A reference to the Database.BatchableContext object.
• A list of sObjects, such as List<sObject>, or a list of parameterized types. If you are using a
Database.QueryLocator, use the returned list.
finish
Used to execute post-processing operations (for example, sending an email) and is called once after
all batches are processed
Here’s what the skeleton of a Batch Apex class looks like:
@future
static void myFutureMethod(List<String> params) {
// call synchronous method
mySyncMethod(params);
}
Chaining Jobs
One of the best features of Queueable Apex is job chaining. If you ever need to run jobs
sequentially, Queueable Apex could make your life much easier. To chain a job to another job,
submit the second job from the execute() method of your queueable class. You can add only one
job from an executing job, which means that only one child job can exist for each parent job. For
example, if you have a second class called SecondJob that implements the Queueable interface, you
can add this class to the queue in the execute() method as follows:
Scheduled Apex
The Apex Scheduler lets you delay execution so that you can run Apex classes at a specified time.
This is ideal for daily or weekly maintenance tasks using Batch Apex. To take advantage of the
scheduler, write an Apex class that implements the Schedulable interface, and then schedule it for
execution on a specific schedule.
Scheduled Apex Syntax
To invoke Apex classes to run at specific times, first implement the Schedulable interface for the
class. Then, schedule an instance of the class to run at a specific time using the System.schedule()
method.
public class SomeClass implements Schedulable {
public void execute(SchedulableContext ctx) {
// awesome code here
}
}
The class implements the Schedulable interface and must implement the only method that this
interface contains, which is the execute() method.
The parameter of this method is a SchedulableContext object. After a class has been scheduled, a
CronTrigger object is created that represents the scheduled job. It provides a getTriggerId() method
that returns the ID of a CronTrigger API object.
Monitoring Asynchronous Jobs
The great thing about async jobs is that they work silently in the background. The tough thing about
async jobs is that they work silently in the background. Luckily there are a few ways to monitor
what is going on with your jobs under the covers.
You can monitor the status of all jobs in the Salesforce user interface. From Setup, enter Jobs in the
Quick Find box, then select Apex Jobs.
The Apex Jobs page shows all asynchronous Apex jobs with information about each job’s execution.
The following screenshot shows one future method job and two completed batch jobs for the same
Batch Apex class.
If you have many batch jobs, use the Batch Jobs page to view only batch jobs. To open the Apex
Batch Jobs page, click the link at the top of the Apex Jobs page. Use the slider in the Apex Batch
Jobs page to select a specific date range and narrow down the list of batch jobs displayed. You can
view past jobs that haven’t been deleted yet. The Batch Jobs page groups jobs by the batch class.
Click More Info next to a class ID you’re interested in to find out details about the jobs executed
for that class. This image shows the popup that displays after clicking More Info. This batch class
has two jobs that executed successfully.
You can also monitor the status of Apex jobs in the Apex Flex Queue, and reorder them to control
which jobs are processed first. From Setup, enter Jobs in the Quick Find box, then select Apex Flex
Queue.
Monitoring Future Jobs
Future jobs show up on the Apex Jobs page like any other jobs. However, future jobs are not part of
the flex queue currently.
You can query AsyncApexJob to find your future job, but there’s a caveat. Since kicking off a future
job does not return an ID, you have to filter on some other field such as MethodName, or JobType, to
find your job. There are a few sample SOQL queries in this Stack Exchange post that might help.
Monitoring Queued Jobs with SOQL
To query information about your submitted job, perform a SOQL query on AsyncApexJob by
filtering on the job ID that the System.enqueueJob() method returns.
AsyncApexJob jobInfo = [SELECT Status, NumberOfErrors
FROM AsyncApexJob WHERE Id = :jobID];
Monitoring Queue Jobs with the Flex Queue
The Apex Flex queue enables you to submit up to 100 batch jobs for execution. Any jobs that are
submitted for execution are in holding status and are placed in the Apex Flex queue. Up to 100
batch jobs can be in the holding status.
Jobs are processed first-in first-out—in the order in which they’re submitted. You can look at the
current queue order and shuffle the queue, so that you could move an important job to the front, or
less important ones to the back.
REST callouts are based on HTTP. To understand how callouts work, it’s helpful to understand a few
things about HTTP. Each callout request is associated with an HTTP method and an endpoint. The HTTP
method indicates what type of action is desired.
The simplest request is a GET request (GET is an HTTP method). A GET request means that the sender
wants to obtain information about a resource from the server. When the server receives and processes this
request, it returns the request information to the recipient. A GET request is similar to navigating to an
address in the browser. When you visit a web page, the browser performs a GET request behind the scenes.
In the browser, the result of the navigation is a new HTML page that’s displayed. With a callout, the result
is the response object.
To illustrate how a GET request works, open your browser and navigate to the following URI: https://th-
apex-http-callout.herokuapp.com/animals. Your browser displays a list of animals in a weird format,
because the service returns the response in a format called JSON. Sometimes a GET response is also
formatted in XML.
The following are descriptions of common HTTP methods.
Table 1. Some Common HTTP Methods
It’s time to put your new HTTP knowledge to use with some Apex callouts. This example sends a GET
request to a web service to get a list of woodland creatures. The service sends the response in JSON
format. JSON is essentially a string, so the built-in JSONParser class converts it to an object. We can
then use that object to write the name of each animal to the debug log.
Before you run the examples in this unit, you’ll need to authorize the endpoint URL of the callout,
https://th-apex-http-callout.herokuapp.com, using the steps from the Authorize Endpoint Addresses
section.
20. After the debug log opens, select Debug Only to view the output of the System.debug
statements. The names of the animals are displayed.
The JSON for our example is fairly simple and easy to parse. For more complex JSON structures,
you can use JSON2Apex. This tool generates strongly typed Apex code for parsing a JSON structure.
You simply paste in the JSON, and the tool generates the necessary Apex code for you. Brilliant!
Send Data to a Service
Another common use case for HTTP callouts is sending data to a service. For instance, when you
buy the latest Justin Bieber album or comment on your favorite “Cat in a Shark Costume Chases a
Duck While Riding a Roomba” video, your browser is making a POST request to submit data. Let’s
see how we send data in Apex.
This example sends a POST request to the web service to add an animal name. The new name is added
to the request body as a JSON string. The request Content-Type header is set to let the service know that
the sent data is in JSON format so that it can process the data appropriately. The service responds by
sending a status code and a list of all animals, including the one you added. If the request was processed
successfully, the status code returns 201, because a resource has been created. The response is sent to
the debug log when anything other than 201 is returned.
14. System.debug('The status code returned was not expected: ' + response.getStatusCode() + ' '
+ response.getStatus());
15. } else {
16. System.debug(response.getBody());
}
17. Select Open Log, and then click Execute.
18. When the debug log opens, select Debug Only to view the output of the System.debug
statement. The last item in the list of animals is "mighty moose".
Generate an Apex Class from the WSDL
1. From Setup, enter Apex Classes in the Quick Find box, then click Apex Classes.
2. Click Generate from WSDL.
3. Click Choose File and select the downloaded calculator.wsdl file.
4. Click Parse WSDL.
The application generates a default class name for each namespace in the WSDL document
and reports any errors.
For this example, use the default class name. However, in real life it is highly recommended that
you change the default names to make them easier to work with and make your code more intuitive.
It's time to talk honestly about the WSDL parser. WSDL2Apex parsing is a notoriously fickle
beast. The parsing process can fail for several reasons, such as an unsupported type, multiple
bindings, or unknown elements. Unfortunately, you could be forced to manually code the Apex
classes that call the web service or use HTTP.
5. Click Generate Apex code.
The final page of the wizard shows the generated classes, along with any errors. The page
also provides a link to view successfully generated code.
Making your Apex class available as a REST web service is straightforward. Define your class as
global, and define methods as global static. Add annotations to the class and methods. For
example, this sample Apex REST class uses one method. The getRecord method is a custom REST
API call. It's annotated with @HttpGet and is invoked for a GET request.
@RestResource(urlMapping='/Account/*')
@HttpGet
global static Account getRecord() {
// Add your code
}
}
As you can see, the class is annotated with @RestResource(urlMapping='/Account/*'). The base
endpoint for Apex REST is https://yourInstance.my.salesforce.com/services/apexrest/. The URL
mapping is appended to the base endpoint to form the endpoint for your REST service. For example,
in the class example, the REST endpoint is
https://yourInstance.my.salesforce.com/services/apexrest/. For your org, it could look something
like, https://yourInstance.my.salesforce.com/services/apexrest/Account/*.
In this module when you see “yourInstance” in links or code be sure to change it out with
your Salesforce Org instance.
The URL mapping is case-sensitive and can contain a wildcard character (*).
Define each exposed method as global static and add an annotation to associate it with an HTTP
method. The following annotations are available. You can use each annotation only once in each Apex
class.
Annotation Action Details
Making your Apex class available as a SOAP web service is as easy as with REST. Define your
class as global. Add the webservice keyword and the static definition modifier to each method you
want to expose. The webservice keyword provides global access to the method it is added to.
For example, here's a sample class with one method. The getRecord method is a custom SOAP
API call that returns an Account record.
@SoapResource(urlMapping='/Account/*')
global with sharing class MySOAPWebService {
webservice static Account getRecord(String id) {
// Add your code
}
}
The external application can call your custom Apex methods as web service operations by consuming the
class WSDL file. Generate this WSDL for your class from the class detail page, accessed from the Apex
Classes page in Setup. You typically send the WSDL file to third-party developers (or use it yourself) to
write integrations for your web service.
Because platform security is a first-class Salesforce citizen, your web service requires authentication. In
addition to the Apex class WSDL, external applications must use either the Enterprise WSDL or the
Partner WSDL for login functionality.