Thursday, February 15, 2018

Apex Webservice (You Call me)

I already write about Apex Call Out when we want to connect with external services either in REST or SOAP here .

If Apex Call Out I use 'I call you' metaphor to represent Salesforce need to contact external service, therefore we need external service info such as - url and set end point url in Remote Site Setting.

While Apex Web Service I use 'You call me' which mean we need to expose our Apex class either as SOAP or REST for external service to connect.

You call me! In order for them to you,
you need to give your phone number

Expose a class as REST Service

  1. Define class with global access modifier .
  2. Use @RestResource annotation at class level to enable it serve as webservice
    • Example : @RestResource(urlMapping='/Case/*')
  3. Define method with global static .
  4. Add an annotation to associate with Http method. Bear in mind on one method is allowed per class. It means there should be only one GET method per class.
  5. Endpoint URL that we need to share to external service will look like this: https://yourInstance.salesforce.com/services/apexrest/Case/*
AnnotationActionDetails
@HttpGetReadReads or retrieves records.
@HttpPostCreateCreates records.
@HttpDeleteDeleteDeletes records.
@HttpPutUpsertTypically used to update existing records or create records.
@HttpPatchUpdateTypically used to update fields in existing records.
Example
@RestResource(urlMapping='Cases/*')
global with sharing class MyRestResource {
    @HttpGet
    global static Case getRecord() {
        // Add your code
    }
}


Expose a class as SOAP Service

  1. Define class with global access modifier .
  2. Define your method with 'webservice static'
  3. You need to generate WSDL and send it to the external developer so they can write integration to connect wit us.
Example
global class Project {
  
   webservice String area; 
   webservice String region; 
   
   //Define an object in apex that is exposed in apex web service
   global class Plan {
      webservice String name;
      webservice Integer planNumber;
      webservice Date planningPeriod;
      webservice Id planId;
   }

   webservice static Plan createProjectPlan(Plan vPlan) {
       
       //A plan maps to the Project__c object in salesforce.com. 
       //So need to map the Plan class object to Project__c standard object
       Project__c proj = new Project__c();
       proj.Name = vPlan.name;
       proj.AccountNumber = String.valueOf(vPlan.planNumber);
       insert proj;
       
       vPlan.planId=proj.Id;
       return vPlan;
  }

Conclusion

This entry explains on custom Apex code for REST and SOAP API and it not the only way for external applications to connect with Salesforce. There a few ways to connect such as using Salesforce's REST and SOAP APIs. It has different strengths to fulfill  business requirement.

References :
Awesome Trailhead Apex Web Services
Still standing : Apex Web Services and Callouts

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