Salesforce Summaries – Integrating Third-party APIs Using APEX RESTful Callouts

SalesforceSummaries: a series delivering key insights from Salesforce YouTube videos, to save you time as you keep up to date with the latest technological changes within the Salesforce ecosystem.

Introduction:

In this presentation, you will learn how to integrate the Force.com platform with data stored on a third party web service.

Details: ‘Integrating Third-party APIs Using APEX RESTful Callouts

Presenter: Matt Kaufman, Jenna Tucker

Details: 25 minutes

Key Terms: REST API, RESTful Callouts, HttpResponse

[email protected] — You will learn how to pull outside data into Salesforce.

[email protected] — In this presentation, you will learn how to integrate the Force.com platform with StackExchange to work with Force.com related questions.

[email protected] — It’s important to know about RESTful callouts. REST stands for Representational State Transfer, and it is a way which web services talk to each other.

So even if you have two web services that have been built with different technologies, they can still communicate with each other using REST.

Information is typically transferred as HTML, XML or JSON.

[email protected] — JSON stands for JavaScript Object Notation and is typically a much faster way to transfer data than using XML, which is a bit more rigid.

[email protected] — This is a high level diagram of what is happening when we perform an Apex callout to a third party web service. A callout from the Force.com server to another server is completed over the internet. The server will then return a response to the Force.com server.

This could be used for processing credit cards, validating data, or even augmenting data (bringing data into the Force.com server).

[email protected] — Built into Apex, we have an HttpRequest, Http and HttpResponse class. These classes can be used to perform a callout. In addition, Apex also includes a JSON class that makes it very easy to work with JSON strings to help make the response very humanly readable.

[email protected] — However, before any callout can be achieved, you will first have to create a remote site setting. A remote site setting says ‘this is a URL that we will allow our code to contact’. This helps data from being sent from your Salesforce org to an incorrect endpoint by mistake.

[email protected] — Using the HttpRequest class, we instantiate an object which defines what we want to do (how we want to communicate to the web server, what attributes should be specified etc). In the below example, you can see that we instantiate an httpRequest() object and we use the setMethod method to specify a GET call to a specific endpoint.

[email protected] — The easiest class to work with for calling out to a web service is the Http class. It’s very simple. You instantiate it and then send the request. You receive an httpResponse.

[email protected] — Finally, there is the HttpResponse class. This class includes methods to read the response from the 3rd party service. You can turn the response into an Apex object which your code can read.

[email protected] — A preferable approach is to create a single method which completes all of the operations that you want in order to communicate with the third party service.

An example is below, as per the GitHub repo here.

In the below snippet of code, the method ‘callout’ passes in the verb of the httpMethod, the endpoint and the body of the message.

public with sharing class stackExchangeAPI {

public static String BASE_URL = ‘https://api.stackexchange.com/2.2/';

//Method to perform a callout and return an httpResponse

public static httpResponse callout(String httpMethod, String endpoint, String body){

//Instantiate an httpRequest and set the required attributes

httpRequest req = new httpRequest();

req.setMethod(httpMethod);

req.setEndpoint(endpoint);

//Optional attributes are often required to conform to the 3rd Party Web Service Requirements

req.setHeader(‘Accept-Encoding’,’gzip, deflate’);

//You can adjust the timeout duration (in milliseconds) to deal with slow servers or large payloads

req.setTimeout(120000);

//Use the HTTP Class to send the httpRequest and receive an httpResposne

/*If you are not using an HttpCalloutMock:

if (!test.isRunningTest){

*/

httpResponse res = new http().send(req);

/*If you are not using an HttpCalloutMock:

}

*/

system.debug(res.toString());

system.debug(res.getBody());

return res;

}

[email protected] — Typically, HttpResponse bodies are not human readable.

[email protected] — To understand more about what the raw response will typically look like, you can go to the URI http://api.stackexchange.com/2.2/questions?order=desc&sort=activity&site=salesforce.

You can make this more human readable using the ‘parse’ option in Google Chrome or you can use a tool like JSON Pretty Print. Alternatively, you could use a Chrome extension like Postman or ARC (Advanced REST Client); which gives you additional information as well as the option to choose the raw or prettified response.

[email protected] — So having looked at the response and looking at the definition and attributes of the response, once we understand what we should be getting back, all we need to do is to code that in Apex.

This can be achieved by serializing and deserialising the JSON strings into Apex objects.

So in this example, by de-serialising the httpResponse from a JSON string into an object, we can use Apex to work with the response.

[email protected] — So let’s delve into the code in more detail to see how we will handle this in Apex. In the outermost class ‘responseResource’, we have attributes which represent the attributes that are in the body of the message returned from the API.

For example, if you change the request URL from http://api.stackexchange.com/2.2/questions?order=desc&sort=activity&site=salesforce to an incorrect URL, say, http://api.stackexchange.com/2.2/questionsTHISISWRONG?order=desc&sort=activity&site=salesforce, then the response returns the following:

Whereas, if the request is success (a ‘200’ response), then the response returns the following attributes:

These attributes make up the response resource; which you can see are defined in the Apex code of the method below:

In addition to these attributes, a List is also specified: public List items {get; set;}

This list is populated with the questionResource records; which are also defined in the API response.

[email protected] — By looking at the response from a successful GET call to the URI, we can see the following:

Some of these attributes are specified in the questionResource class in the Apex code. What’s interesting to point out here is that you do not need to specify all of the attributes from the API response, only those that you care about. This is in sharp contrast to XML, which must be in alignment.

[email protected] — What you’ll notice is that the ‘owner’ attribute of the questionResource class is also a class ‘userResource’. This is because, as per the API response, the ‘owner’ attribute is represented as an object:

So, overall, we are working with 3 different objects. This is quite hard to read because we have multiple nested objects. However, to make this easier to read, we can create a Visualforce page and a controller.

Also, please note: if the JSON string that comes back as part of your response has an attribute that isn’t defined in the code, then your code just ignores it but if it’s the wrong data type, then an exception will be thrown. Conversely, if you’ve defined an attribute in your class but the response doesn’t contain that attribute, then it’ll be set to null.

[email protected] — As per the constructor, the endpoint is being defined ahead of time. You may choose to have the endpoint defined on the fly, though.

[email protected] — When performing the callout, the same code that was written before is being leveraged.

[email protected] — Then, the response is deserialized.

[email protected] — The code for the Visualforce page looks very typical. There’s a section called ‘JSON Deserializer’, which outputs the instances of the responses in a tabular format.

[email protected] — So when one selects ‘Callout’ on the page, the getBody() responses returns the raw JSON:

And by selecting ‘Deserialize’, the JSON is deserialized into an Apex object; which the code is working on.

[email protected] — An important thing to note is that you cannot perform a callout in a test method.

In this example, the code coverage is only 8% as the callout itself hasn’t been tested. This means that you cannot deploy to Production.

[email protected] — The problem here is that the callout is in the test method itself, hence, it isn’t being run.

[email protected] — In the past, you would just add a condition to say ‘if the test is not running, perform this callout’.

However, this means that a proper test is not in place. The test should test that the response that is given back is properly parsed.

[email protected] — So Salesforce created a way to perform meaningful tests on callouts using the httpCalloutMock interface. This interface enables you to mock the callout to test the response.

[email protected] — And so in the code of the testHttpCalloutMock.cls, we create instances of questionResources.

This allows you to do a meaningful test on the callout. This time around, the code coverage passes.

[email protected] — At a high level, this is how the httpCalloutMock interface works:

Instead of calling out to the web service via the internet and saying ‘I’m calling you, but please don’t take this seriously, this is just a test’, the mock callout is done on the Force.com servers.

[email protected] — Remember to use the setMock() method in your test method.

[email protected] — You can set multiple mock interfaces, but it’s the last mock interface that you set that will be used. However, a smart approach would be to have a single Mock Interface and then query the endpoint. If the endpoint was A, then set the object in the response to X, but if the endpoint was B, then set the object in the response to Y.

One thought on “Salesforce Summaries – Integrating Third-party APIs Using APEX RESTful Callouts

Leave a Reply