SFDC Stop - Always the latest about Salesforce


Full Tutorial Series with videos, free apps, live sessions, salesforce consulting and much more.


Telegram logo   Join our Telegram Channel

Tuesday 3 December 2019

Salesforce Integration Tutorial Part 8 - Apex REST Callouts

Hello Trailblazers,

Welcome to the 8th tutorial of the Salesforce Integration Tutorial series. In previous tutorials, we created a test class for our custom API in salesforce and we've gone through different methods that are available while creating our custom APIs.

In this tutorial, we're not going to create an API in salesforce instead, we'll be calling out an API hosted on an external system from our salesforce org and will get the response from that API. For this purpose, mainly 3 predefined classes are used:-

  1. HttpRequest:- This class is used to create a new HTTP Request to be sent to the external system. It has methods like:- setMethod(), setHeader(), setBody() which are used to set the parameters of HTTP Request.
  2. HttpResponse:- This class is used to store the HTTP Response which is returned from the external system. It has methods like:- getBody(), getStatus(), getStatusCode() which are used to get the data returned in the response.
  3. Http:- This class is used to send an HTTP request to an external API and get the response from that API. It has just two methods:- send() and toString() out of which send() is mostly used. This method takes an instance of HttpRequest as a parameter and return an instance of HttpResponse in the response.

I have created a custom API and deployed it to Heroku, you can have a look at the same here:- https://sfdcstop.herokuapp.com/blogs

This API is simply returning a response as below:-


As you can see above, the response of this API consists of an author as Rahul Malhotra and a list of blogs written by me in the Salesforce Integration Tutorial Series along with the URL of each blog. Now, our task is to call this API from Salesforce and get the response. For this, we first need to create a wrapper class that can parse this JSON response in apex. Fortunately, we have a great tool available for this and it's free. The tool is called JSON2Apex and is available at:- https://json2apex.herokuapp.com/

In this tool, you just need to paste the json which is returned by the API, specify the wrapper class name and click on the Create Apex button. This will download the zip file in your system which consists of a wrapper class that can be used to parse the input json and a test class for that wrapper class. In our case, I am pasting the json returned by my api below:-


As I clicked on Create Apex button, I got the below apex classes that I created in my salesforce org after minor modifications (Added comments and removed _ from the name of test class. Updated SFDCStopBlogsWrapper_Test to SFDCStopBlogsWrapperTest).

You can see above that the wrapper class SFDCStopBlogsWrapper has two data members:- author of type string and blogs of type List<Blogs> where Blogs is the inner class that consists of id, title, and url as string. It can be used to parse the input json which we got in the response as the json consits of author which is a string and list of blogs that are objects consisting of id, title and url which are again strings. The wrapper class also consists of parse() method that is taking the json string as an input and will return an instance of the same wrapper class. It's using JSON.deserialize() method to deserialize the json string. Similarly, you can have a look at the test class code for this wrapper below:-

As you can see above, it consists of a single testmethod that's parsing the same json string that was used in the input while downloading the auto-generated apex classes. This method is just calling the parse() method of wrapper class as it's the only method in the wrapper class. Then it's checking whether the JSON string is parsed properly or not by confirming that the instance of wrapper class is not null.

To make an HTTP callout to an external API, we need to add an entry to the Remote Site Settings in Salesforce where we need to store the base URL of the api. We need to do this to tell Salesforce that we trust this external API/Endpoint URL and thereby, allowing salesforce to use this endpoint to interact with the external system.

For this, go to setup and search for remote site settings:-


You'll see the below page:-


 Click on New Remote Site and add the following data:-


You can see above that I have added only the base URL i.e. https://sfdcstop.herokuapp.com for the remote site setting and not the actual blogs api url i.e. https://sfdcstop.herokuapp.com/blogs. I have done this so that I don't need to create multiple entries for each API in future as Salesforce will be allowed to interact with anything following this base URL. Click on Save.

You'll see that a new remote site record is created. Now, we're ready to create our callout class that will send a request to the external api, get the response and will use the wrapper class to parse that JSON response. I created a new class named SFDCStopCallout. It's code is given below:-

As you can see above, I have a single method in this class named as getBlogs() which will hit the blogs API and get the response from there. Inside this method, I have created and initialized an instance of Http class and HttpRequest class. I used the instance of HTTPRequest class named as:- request and called it's setEndpoint() method in which I passed the endpoint url of our blogs api. Then I called the setMethod() method of request and passed the value GET as we need to send a GET request to the api endpoint. Finally, I used the send() method from the instance of  Http class that will take request (instance of HttpRequest) as a parameter and return an instance of HttpResponse class. The response is assigned to an instance of HttpResponse class named as response. The send() method will actually send the request to the endpoint URL and get the response from there. Finally, I checked if the response status code is 200 by using the getStatusCode() method of response. If it is, I got the response body which is a json string using getBody() method of response. I used the parse() method from my SFDCStopBlogsWrapper class to parse the json string that I got in the response body.

Finally, I used the author variable of my wrapper class to display the author in logs and then I checked if the blogs variable is not null and not empty. If I have the blogs in the response, I iterated those blogs one by one and displayed the id, title and url of each blog.

You can execute this callout in the developer console by calling the getBlogs() method of SFDCStopCallout class as:- SFDCStopCallout.getBlogs(). Then you can check the debug logs to see the response as given below:-



Tired of reading or just scrolled down, don't worry, you can watch the video too.



That's all for this tutorial. We learned how to make a callout to external API from Salesforce and get the response in apex. We also learned about the concept of wrapper classes and got to know about remote site settings. In case you need to pass the data to the external system, you can either pass it in the URL itself or set the data in the request body using the setBody() method of HttpRequest class. In that case you should also set the appropriate method like:- POST, PUT etc. as GET doesn't support the request body. You can have a look at all the methods of HttpRequest class here.

In the next tutorial, we'll create a test class for this api callout. If you liked this tutorial, make sure to share it in your network and let me know your feedback in the comments below.

Happy Trailblazing..!!

11 comments:

  1. Hi thanks for the video. In my case i wanna fetch data from my application (or from localhost ) to the salesforce where i can display the data. i want that when any user is register to my application i can see the user to my salesforce account. please help me. thank you.

    ReplyDelete
    Replies
    1. Hi,

      You can't connect it to localhost. You should host your application on an actual server (like I have hosted on heroku), have an API endpoint of your application that can be called from Salesforce. Then you can fetch and display the data in a lightning component and finally add that lightning component to the account detail page.

      Hope that helps..!!

      Delete
  2. How and where use this data in mu salesforce account please explain.

    ReplyDelete
  3. Rahul - Can you please help me with following error while deserializing JSON. Error : Malformed JSON: Expected '{' at the beginning of object. With the help of your code I am trying to use Postal India API, but getting error at (postalDetails = PostalWrapperClass.deserialize(response.getBody());), below is the code

    Code

    public class PostalApiCall {
    @AuraEnabled
    public static PostalWrapperClass fetchPostOfficeDetails(String postalCode){
    system.debug('Inside server method to execute details');
    PostalWrapperClass postalDetails = new PostalWrapperClass();
    HTTPRequest request = new HTTPRequest();
    request.setEndpoint('https://api.postalpincode.in/pincode/'+postalCode);
    request.setMethod('GET');
    HTTP objHTTP = new HTTP();
    HTTPResponse response = objHTTP.send(request);
    system.debug('Response is'+ response.getBody());
    //String rawData = response.getBody().toString();
    //PostalWrapperClass pw = new PostalWrapperClass();
    //postalDetails = (PostalWrapperClass)System.JSON.deserialize(response.getBody(), PostalWrapperClass.class);
    //response = (stackExchangeAPI.responseResource)JSON.deserialize(responseBody,stackExchangeAPI.responseResource.class);
    //system.debug('#######'+pw);
    postalDetails = PostalWrapperClass.deserialize(response.getBody());
    system.debug('Postal details after Deserialization ::' + postalDetails);
    return postalDetails;
    }
    }

    public class PostalWrapperClass {
    @AuraEnabled
    public String Message;
    @AuraEnabled
    public String Status;
    @AuraEnabled
    public List PostOffice;

    public class PostOffice{
    @AuraEnabled
    public String Name;
    @AuraEnabled
    public String Description;
    @AuraEnabled
    public String BranchType;
    @AuraEnabled
    public String DeliveryStatus;
    @AuraEnabled
    public String Circle;
    @AuraEnabled
    public String District;
    @AuraEnabled
    public String Division;
    @AuraEnabled
    public String Region;
    @AuraEnabled
    public String State;
    @AuraEnabled
    public String Country;
    }
    public static PostalWrapperClass deserialize(String res){
    return (PostalWrapperClass)JSON.deserialize(res, PostalWrapperClass.class);
    }
    }

    ReplyDelete
    Replies
    1. Hi Sasiraja, most commonly this issue is coming because your wrapper is not correct. Try creating a wrapper using this tool for your JSON:- https://json2apex.herokuapp.com/

      Delete
  4. Great post with all minute details

    ReplyDelete
  5. No seu callout como você faria para tratar um retorno código 500 com o "try and catch"?

    ReplyDelete
  6. In your callout how would you handle a code 500 return with "try and catch"?

    ReplyDelete
    Replies
    1. You can use response.getStatusCode() to check the code and manage it accordingly.

      Delete
  7. thanks buddy

    ReplyDelete