Friday, February 09, 2018

Apex Call out (I Call You)

Although I have done integration to external service using call out in my previous experience still I have hiccup to grab the concept.So I thought that I should sit down and learn the concept and of course  the best way is  through Salesforce Trailhead  =) .

When it comes to integrate Salesforce with external service we can categorize it into two types :
  1. Apex Call Out
  2. Apex Web Service (I wrote here)
Both can use SOAP and REST protocol which it is advisable to use REST. In case you want to know which one better , please check out this article.

I personally have come out easy way to understand the concept for both category.In my concept, we can assume SOAP and REST is different provider that use different format.

I use 'I Call You' for Apex Call Out and 'You Call Me' for Apex Webservices.

I Call You (Apex Call Out)

well, can you see..my drawing is #awesome =)

I mean Salesforce , You mean external service.
In order to enable this we need to know who we call so we can call them.
They need to let us know how to call them.

You Call Me (Apex Web Service)
The drawing become bigger for unknown reason
You mean External Service, me mean Salesforce.
In order to enable this we need to expose and give information to external service how to call us.

Apex Call Out

Apex Call Out is when we want to use external service , either we want to send or receive data.
I notice that in Trailhead it use webservice call out to define call out that use SOAP and HTTP Call out to define call out that use REST with JSON.
  • 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.Read more...

Regardless what type we still need to define their number(Endpoint Address) in Remote Setting so we can call them.

Apex REST Callouts

Some common HTTP methods
HTTP MethodDescription
GETRetrieve data identified by a URL.
POSTCreate a resource or post data to the server.
DELETEDelete a resource identified by a URL.
PUTCreate or replace the resource sent in the request body.

Basic Steps to implement Apex REST Callouts
  1. Define Endpoint address in Remote Setting.Note the setting below will authorize all subfolders for the endpoint, for example in your code later it will enable you to call https://th-apex-http-callout.herokuapp.com/subfolder1 or https://th-apex-http-callout.herokuapp.com/subfolder2
  2. Make sure external service give you information how to access their data.They should provide you correct URL to retrieve animal data and what parameter they need in order to return you the data. For example, they provide you this url https://th-apex-http-callout.herokuapp.com/animals/'+id which indicate that you can append Id at the back in order for it to return animal data.Without information, you not able to call them.Usually they will provide you documentation on how you able to call their method.
  3. You can create class to get the data or you can run it using Apex Execute Anonymous in Developer Console.
    public class AnimalLocator {
    public class cls_animal {
            public Integer id;  
            public String name; 
            public String eats; 
            public String says; 
        }    
    
    public class JSONOutput{
        public cls_animal animal;
    
     }
    public static String getAnimalNameById(Integer id){
      String stranimal='';
    
     Http http = new Http();
            HttpRequest request = new HttpRequest();
            request.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals/'+id);
            request.setMethod('GET');
            HttpResponse response = http.send(request);
            // If the request is successful, parse the JSON response.
            if (response.getStatusCode() == 200) {
              // Deserializes the JSON string into collections of primitive data types.
              jsonOutput results = (jsonOutput) JSON.deserialize(response.getBody(), jsonOutput.class);
               strAnimal=results.animal.name;
               System.debug(stranimal);
             }
           
    return stranimal;
    }
    
    }
    


Apex SOAP Callouts

In this case, we need to request external party to provide us WSDL so we can generate class from it.
In trailhead , the external service provide calculator.xml like below.

<?xml version='1.0' encoding='UTF-8'?><wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://calculator.services/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="CalculatorImplService" targetNamespace="http://calculator.services/">
  <wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://calculator.services/" elementFormDefault="unqualified" targetNamespace="http://calculator.services/" version="1.0">

  <xs:element name="doAdd" type="tns:doAdd"/>

  <xs:element name="doAddResponse" type="tns:doAddResponse"/>

  <xs:element name="doDivide" type="tns:doDivide"/>

  <xs:element name="doDivideResponse" type="tns:doDivideResponse"/>

  <xs:element name="doMultiply" type="tns:doMultiply"/>

  <xs:element name="doMultiplyResponse" type="tns:doMultiplyResponse"/>

  <xs:element name="doSubtract" type="tns:doSubtract"/>

  <xs:element name="doSubtractResponse" type="tns:doSubtractResponse"/>

  <xs:complexType name="doDivide">
    <xs:sequence>
      <xs:element minOccurs="0" name="arg0" type="xs:double"/>
      <xs:element minOccurs="0" name="arg1" type="xs:double"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="doDivideResponse">
    <xs:sequence>
      <xs:element minOccurs="0" name="return" type="xs:double"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="doSubtract">
    <xs:sequence>
      <xs:element minOccurs="0" name="arg0" type="xs:double"/>
      <xs:element minOccurs="0" name="arg1" type="xs:double"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="doSubtractResponse">
    <xs:sequence>
      <xs:element minOccurs="0" name="return" type="xs:double"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="doMultiply">
    <xs:sequence>
      <xs:element minOccurs="0" name="arg0" type="xs:double"/>
      <xs:element minOccurs="0" name="arg1" type="xs:double"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="doMultiplyResponse">
    <xs:sequence>
      <xs:element minOccurs="0" name="return" type="xs:double"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="doAdd">
    <xs:sequence>
      <xs:element minOccurs="0" name="arg0" type="xs:double"/>
      <xs:element minOccurs="0" name="arg1" type="xs:double"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="doAddResponse">
    <xs:sequence>
      <xs:element minOccurs="0" name="return" type="xs:double"/>
    </xs:sequence>
  </xs:complexType>

</xs:schema>
  </wsdl:types>
  <wsdl:message name="doSubtractResponse">
    <wsdl:part element="tns:doSubtractResponse" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="doMultiplyResponse">
    <wsdl:part element="tns:doMultiplyResponse" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="doAddResponse">
    <wsdl:part element="tns:doAddResponse" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="doDivide">
    <wsdl:part element="tns:doDivide" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="doSubtract">
    <wsdl:part element="tns:doSubtract" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="doDivideResponse">
    <wsdl:part element="tns:doDivideResponse" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="doMultiply">
    <wsdl:part element="tns:doMultiply" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="doAdd">
    <wsdl:part element="tns:doAdd" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="Calculator">
    <wsdl:operation name="doDivide">
      <wsdl:input message="tns:doDivide" name="doDivide">
    </wsdl:input>
      <wsdl:output message="tns:doDivideResponse" name="doDivideResponse">
    </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="doSubtract">
      <wsdl:input message="tns:doSubtract" name="doSubtract">
    </wsdl:input>
      <wsdl:output message="tns:doSubtractResponse" name="doSubtractResponse">
    </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="doMultiply">
      <wsdl:input message="tns:doMultiply" name="doMultiply">
    </wsdl:input>
      <wsdl:output message="tns:doMultiplyResponse" name="doMultiplyResponse">
    </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="doAdd">
      <wsdl:input message="tns:doAdd" name="doAdd">
    </wsdl:input>
      <wsdl:output message="tns:doAddResponse" name="doAddResponse">
    </wsdl:output>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="CalculatorImplServiceSoapBinding" type="tns:Calculator">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="doDivide">
      <soap:operation soapAction="" style="document"/>
      <wsdl:input name="doDivide">
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="doDivideResponse">
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="doSubtract">
      <soap:operation soapAction="" style="document"/>
      <wsdl:input name="doSubtract">
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="doSubtractResponse">
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="doMultiply">
      <soap:operation soapAction="" style="document"/>
      <wsdl:input name="doMultiply">
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="doMultiplyResponse">
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="doAdd">
      <soap:operation soapAction="" style="document"/>
      <wsdl:input name="doAdd">
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="doAddResponse">
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="CalculatorImplService">
    <wsdl:port binding="tns:CalculatorImplServiceSoapBinding" name="CalculatorImplPort">
      <soap:address location="https://th-apex-soap-service.herokuapp.com/service/calculator"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

Basic Steps to implement Apex SOAP Callouts
  1. Define Endpoint address in Remote Setting.
  2. Generate class from WSDL file that you retrieve from external service.Go to Setup > Develop > Apex Classes and hit button Generate from WSDL and wallahhh... the class is ready for you to use.Use the class as usual.

I will write about Apex Web Services later.

Ultimate reference is Apex Integration Services

No comments:

Post a Comment