Unit 5

Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 25

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

trigger HelloWorldTrigger on Account (before insert)


{
for(Account a : Trigger.new)
{
a.Description = 'New description';
}
}
Calling a Class Method from a Trigger
You can call public utility methods from a trigger. Calling methods of other classes enables code
reuse, reduces the size of your triggers, and improves maintenance of your Apex code. It also
allows you to use object-oriented programming.
The following example trigger shows how to call a static method from a trigger. If the trigger was
fired because of an insert event, the example calls the static sendMail() method on the
EmailManager class. This utility method sends an email to the specified recipient and contains the
number of contact records inserted.
trigger ExampleTrigger on Contact (after insert, after delete)
{
if (Trigger.isInsert)
{
Integer recordCount = Trigger.new.size();
// Call a utility method from another class
EmailManager.sendMail('Your email address', 'Trailhead Trigger Tutorial',
recordCount + ' contact(s) were inserted.');
}
else if (Trigger.isDelete) {
// Process after delete
}
}
Triggers and Callouts
Apex allows you to make calls to and integrate your Apex code with external Web services. Apex
calls to external Web services are referred to as callouts. For example, you can make a callout to a
stock quote service to get the latest quotes. When making a callout from a trigger, the callout must
be done asynchronously so that the trigger process doesn’t block you from working while waiting
for the external service's response. The asynchronous callout is made in a background process, and
the response is received when the external service returns it.
To make a callout from a trigger, call a class method that executes asynchronously. Such a method
is called a future method and is annotated with @future(callout=true). This example class contains
the future method that makes the callout.

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() {

HttpRequest request = new HttpRequest();

// Set the endpoint URL.

String endpoint = 'http://yourHost/yourService';

request.setEndPoint(endpoint);

// Set the HTTP verb to GET. request.setMethod('GET');

// 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.

trigger SoqlTriggerBulk on Account(after update)


{
opportunities. List<Account> acctsWithOpps =
[SELECT Id,(SELECT Id,Name,CloseDate FROM
Opportunities) FROM Account WHERE Id IN :Trigger.new];
for(Account a : acctsWithOpps)
{
Opportunity[] relatedOpps = a.Opportunities;
// Do some other processing
}
}
Performing Bulk DML
When performing DML calls in a trigger or in a class, perform DML calls on a collection of
sObjects when possible. Performing DML on each sObject individually uses resources
inefficiently. The Apex runtime allows up to 150 DML calls in one transaction.
This trigger (DmlTriggerNotBulk) performs an update call inside a for loop that iterates over
related opportunities. If certain conditions are met, the trigger updates the opportunity description.
In this example, the update statement is inefficiently called once for each opportunity. If a bulk
account update operation fired the trigger, there can be many accounts. If each account has one or
two opportunities, we can easily end up with over 150 opportunities. The DML statement limit is
150 calls.
This below example (DmlTriggerBulk) shows how to perform DML in bulk efficiently with only
one DML call on a list of opportunities. The example adds the Opportunity sObject to update to a
list of opportunities (oppsToUpdate) in the loop. Next, the trigger performs the DML call outside
the loop on this list after all opportunities have been added to the list. This pattern uses only one
DML call regardless of the number of sObjects being updated.
trigger DmlTriggerBulk on Account(after update)
{

List<Opportunity> relatedOpps = [SELECT Id,Name,Probability FROM Opportunity


WHERE AccountId IN :Trigger.new];
List<Opportunity> oppsToUpdate = new List<Opportunity>();
for(Opportunity opp : relatedOpps)
{

if ((opp.Probability >= 50) && (opp.Probability < 100))


{
opp.Description = 'New description for opportunity’;
oppsToUpdate.add(opp);
}
}
/ Perform DML on a collection
update oppsToUpdate;
}
Apex Unit Tests
The Apex testing framework enables you to write and execute tests for your Apex classes and
triggers on the Lightning Platform. Apex unit tests ensure high quality for your Apex code and let
you meet requirements for deploying Apex.
Testing is the key to successful long-term development and is a critical component of the
development process. The Apex testing framework makes it easy to test your Apex code. Apex
code can only be written in a sandbox environment or a Developer org, not in production. Apex
code can be deployed to a production org from a sandbox. Also, app developers can distribute Apex
code to customers from their Developer orgs by uploading packages to the Lightning Platform
AppExchange. In addition to being critical for quality assurance, Apex unit tests are also
requirements for deploying and distributing Apex.
These are the benefits of Apex unit tests.
• Ensuring that your Apex classes and triggers work as expected
• Having a suite of regression tests that can be rerun every time classes and triggers are updated
to ensure that future updates you make to your app don’t break existing functionality

• 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

Code Coverage Requirement for Deployment


Before you can deploy your code or package it for the Lightning Platform AppExchange, at least
75% of Apex code must be covered by tests, and all those tests must pass. In addition, each trigger
must have some coverage. Even though code coverage is a requirement for deployment, don’t write
tests only to meet this requirement. Make sure to test the common use cases in your app, including
positive and negative test cases, and bulk and single-record processing.
Test Method Syntax
Test methods are defined using the @isTest annotation and have the following syntax:
@isTest static void testName() {
// code_block
}
The @isTest annotation takes multiple modifiers within parentheses and separated by blanks. We’ll
cover one such parameter later.
The visibility of a test method doesn’t matter, so declaring a test method as public or private
doesn’t make a difference as the testing framework is always able to access test methods. For this
reason, the access modifiers are omitted in the syntax.
Test methods must be defined in test classes, which are classes annotated with @isTest. This
sample class shows a definition of a test class with one test method.
@isTest
private class MyTestClass {
@isTest static void myTest() {
// code_block
}
}
Test classes can be either private or public. If you’re using a test class for unit testing only, declare it as
private. Public test classes are typically used for test data factory classes, which are covered later.
Unit Test Example: Test the TemperatureConverter Class
The following simple example is of a test class with three test methods. The class method that’s
being tested takes a temperature in Fahrenheit as an input. It converts this temperature to Celsius
and returns the converted result. Let’s add the custom class and its test class.
In the Developer Console, click File | New | Apex Class, and enter TemperatureConverter for the class name, and
then click OK.

Replace the default class body with the following.


public class TemperatureConverter {

// Takes a Fahrenheit temperature and returns the Celsius equivalent.

public static Decimal FahrenheitToCelsius(Decimal fh) {

Decimal cs = (fh - 32) * 5/9;

return cs.setScale(2);

Press Ctrl+S to save your class.

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);
}
}

Let’s run the methods in this class.


1. In the Developer Console, click Test | New Run.
2. Under Test Classes, click TemperatureConverterTest.
3. To add all the test methods in the TemperatureConverterTest class to the test run, click Add
Selected.
4. Click Run.
5. In the Tests tab, you see 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. They all have green
checkmarks.

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.

Increased Governor and Execution Limits


One of the main benefits of running asynchronous Apex is higher governor and execution
limits. For example, the number of SOQL queries is doubled from 100 to 200 queries when
using asynchronous calls. The total heap size and maximum CPU time are similarly larger for
asynchronous calls.
Asynchronous Apex comes in a number of different flavors. We’ll get into more detail for each one
shortly, but here’s a high level overview.
Type Overview Common Scenarios

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.

Queueable Similar to future methods, but provide additional job Performingsequentialprocessing


Apex chaining and allow more complex data types to be used. operations with external Web services.

Scheduled Schedule Apex to run at a specified time. Daily or weekly tasks.


Apex

How Asynchronous Processing Works


Asynchronous processing, in a multitenant environment, presents some challenges:
Ensure fairness of processing
Make sure every customer gets a fair share of processing resources.
Ensure fault tolerance
Make sure no asynchronous requests are lost due to equipment or software failures. The platform
uses a queue-based asynchronous processing framework. This framework is used to manage
asynchronous requests for multiple organizations within each instance. The request lifecycle is
made up of three parts:
Enqueue
The request gets put into the queue. This could be an Apex batch request, future Apex request or
one of many others. The platform will enqueue requests along with the appropriate data to process
that request.
Persistence
The enqueued request is persisted. Requests are stored in persistent storage for failure recovery and to
provide transactional capabilities.
Dequeue
The enqueued request is removed from the queue and processed. If the processing fails, transaction control ensures
that requests are not lost.
Future Apex
Future Apex is used to run processes in a separate thread, at a later time when system resources
become available.
Note: Technically, you use the @future annotation to identify methods that run asynchronously.
However, because "methods identified with the @future annotation" is laborious, they are commonly
referred to as "future methods" and that’s how we’ll reference them for the remainder of this module.

Future methods are typically used for:


• Callouts to external Web services. If you are making callouts from a trigger or after
performing a DML operation, you must use a future or queueable method. A callout in a
trigger would hold the database connection open for the lifetime of the callout and that is a
"no-no" in a multitenant environment.
• Operations you want to run in their own thread, when time permits such as some sort of
resource-intensive calculation or processing of records.
• Isolating DML operations on different sObject types to prevent the mixed DML error. This
is somewhat of an edge-case but you may occasionally run across this issue. See sObjects
That Cannot Be Used Together in DML Operations for more details.
Future Method Syntax
Future methods must be static methods, and can only return a void type. The specified parameters
must be primitive data types, arrays of primitive data types, or collections of primitive data types.
Notably, future methods can’t take standard or custom objects as arguments. A common pattern is
to pass the method a List of record IDs that you want to process asynchronously.

public class SomeClass {


@future
public static void someFutureMethod(List<Id> recordIds) {
List<Account> accounts = [Select Id, Name from Account Where Id IN :recordIds];
// process account records to do awesome stuff
}
}
The reason why objects can’t be passed as arguments to future methods is because the object can
change between the time you call the method and the time that it actually executes. Remember, future
methods are executed when system resources become available. In this case, the future method may
have an old object value when it actually executes, which can cause all sorts of bad things to happen.

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:

public class MyBatchClass implements Database.Batchable<sObject>


{
public (Database.QueryLocator | Iterable<sObject>) start(Database.BatchableContext bc)
{
// collect the batches of records or objects to be passed to execute
}
public void execute(Database.BatchableContext bc, List<P> records)
{
// process each batch of records
}
public void finish(Database.BatchableContext bc)
{
// execute any post-processing operations
}
}
Queueable Apex
Queueable Apex is essentially a superset of future methods with some extra features. We took the
simplicity of future methods and the power of Batch Apex and mixed them together to form
Queueable Apex! It gives you a class structure that the platform serializes for you, a simplified
interface without start and finish methods and even allows you to utilize more than just primitive
arguments! It is called by a simple System.enqueueJob() method, which returns a job ID that you
can monitor. It beats sliced bread hands down!
Queueable Apex allows you to submit jobs for asynchronous processing similar to future methods
with the following additional benefits:
• Non-primitive types: Your Queueable class can contain member variables of non-primitive
data types, such as sObjects or custom Apex types. Those objects can be accessed when the
job executes.
• Monitoring: When you submit your job by invoking the System.enqueueJob() method, the
method returns the ID of the AsyncApexJob record. You can use this ID to identify your job
and monitor its progress, either through the Salesforce user interface in the Apex Jobs page,
or programmatically by querying your record from AsyncApexJob.
• Chaining jobs: You can chain one job to another job by starting a second job from a running
job. Chaining jobs is useful if you need to do some sequential processing.
Queueable Syntax
To use Queueable Apex, simply implement the Queueable interface.
public class SomeClass implements Queueable
{
public void execute(QueueableContext context)
{
// awesome code here
}
}
Queueable Versus Future
Because queueable methods are functionally equivalent to future methods, most of the time you’ll
probably want to use queueable instead of future methods. However, this doesn’t necessarily mean
you should go back and refactor all your future methods right now.
Another reason to use future methods instead of queueable is when your functionality is sometimes
executed synchronously, and sometimes asynchronously. It’s much easier to re factor a method in
this manner than converting to a queueable class. This is handy when you discover that part of your
existing code needs to be moved to async execution. You can simply create a similar future method
that wraps your synchronous method like so:

@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.

Make Callouts to External Services from Apex


An Apex callout enables you to tightly integrate your Apex code with an external service. The
callout makes a call to an external web service or sends an HTTP request from Apex code, and then
receives the response.
Apex callouts come in two flavors.
• Web service callouts to SOAP web services use XML, and typically require a WSDL
document for code generation.
• HTTP callouts to services typically use REST with JSON.
These two types of callouts are similar in terms of sending a request to a service and receiving a
response. But while WSDL-based callouts apply to SOAP Web services, HTTP callouts can be
used with any HTTP service, either SOAP or REST.
So you are probably asking yourself right now, “Which one should I use?” Whenever possible, use
an HTTP service. These services are typically easier to interact with, require much less code, and
utilize easily readable JSON. All the “cool kids” have been switching to REST services over the
last couple of years, but that's not to say that SOAP Web services are bad. They've been around
forever (in Internet years) and are commonly used for enterprise applications. They are not going
away anytime soon. You'll probably use SOAP mostly when integrating with legacy applications or
for transactions that require a formal exchange format or stateful operations. In this module we'll
touch on SOAP, but will spend most of our time on REST.
Authorize Endpoint Addresses
We love security at Salesforce! So, any time you make a callout to an external site we want to make
sure that it is authorized. We can't have code calling out willy-nilly to any endpoint without prior
approval. Before you start working with callouts, update the list of approved sites for your org on
the Remote Site Settings page.
We'll be using the following endpoints in this module, so go ahead and add them now. If you forget
to add an endpoint, trust me, you'll get a reminder when you try to run your code. We'll be making
calls to the following sites.
• https://th-apex-http-callout.herokuapp.com
• https://th-apex-soap-service.herokuapp.com
Authorize both of these endpoint URLs by following these steps.
1. From Setup, enter Remote Site Settings in the Quick Find box, then click Remote Site
Settings.
2. Click New Remote Site.
3. For the remote site name, enter animals_http.
4. For the remote site URL, enter https://th-apex-http-callout.herokuapp.com. This URL
authorizes all subfolders for the endpoint, like
https://th-apex-http-callout.herokuapp.com/path1 and https://th-apex-http-
callout.herokuapp.com/path2.
5. For the description, enter Trailhead animal service: HTTP.
6. Click Save & New.
7. For the second remote site name, enter animals_soap.
8. For the remote site URL, enter https://th-apex-soap-service.herokuapp.com.
9. For the description, enter Trailhead animal service: SOAP.
10. Click Save.

HTTP and Callout Basics

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

HTTP Method Description

GET Retrieve data identified by a URL.

POST Create a resource or post data to the server.

DELETE Delete a resource identified by a URL.

PUT Create or replace the resource sent in the request body.


Get Data from a Service

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.

1. Open the Developer Console from Setup ( ).


2. In the Developer Console, select Debug | Open Execute Anonymous Window.
3. Delete the existing code and insert the following snippet.
4. Http http = new Http();
5. HttpRequest request = new HttpRequest();
6. request.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals');
7. request.setMethod('GET');
8. HttpResponse response = http.send(request);
9. // If the request is successful, parse the JSON response.
10. if(response.getStatusCode() == 200) {
11. // Deserialize the JSON string into collections of primitive data types.
12. Map<String, Object> results = (Map<String, Object>)
JSON.deserializeUntyped(response.getBody());
13. // Cast the values in the 'animals' key as a list
14. List<Object> animals = (List<Object>) results.get('animals');
15. System.debug('Received the following animals:');
16. for(Object animal: animals) {
17. System.debug(animal);
18. }
}
19. Select Open Log, and then click Execute.

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.

1. Open the Developer Console from Setup ( ).


2. In the Developer Console, select Debug | Open Execute Anonymous Window.
3. Delete any existing code and insert the following snippet.
4. Http http = new Http();
5. HttpRequest request = new HttpRequest();
6. request.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals');
7. request.setMethod('POST');
8. request.setHeader('Content-Type', 'application/json;charset=UTF-8');
9. // Set the body as a JSON object
10. request.setBody('{"name":"mighty moose"}');
11. HttpResponse response = http.send(request);
12. // Parse the JSON response
13. if(response.getStatusCode() != 201) {

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.

Expose a Class as a REST Service

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/*')

global with sharing class MyRestResource {

@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

@HttpGet Read Reads or retrieves records.

@HttpPost Create Creates records.

@HttpDelete Delete Deletes records.

@HttpPut Upsert Typically used to update existing records or create records.

@HttpPatch Update Typically used to update fields in existing records.

Expose a Class as a SOAP Service

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.

You might also like