Monday, March 10, 2014

Testing SalesForce Web Services

Introduction

SalesForce provides an extensive web services support for easier, convenient still secured communication. It supports both SOAP and RestFul web services. There are inbuilt services (like enterprise and partners services), while user can also implement custom services in Apex. This article covers basic testing methods for SalesForce web services. For SOAP based services, I’ve documented steps using SoapUI tool and Simple Java client, while for Rest services, I’ve used cURL utility. This article should be read as helping document for people who are newer in the field of testing sales force web services.
Security Considerations: Note that SalesForce support 2 security mechanism i.e. OAuth2.0 and sessionId. That mean, the authentication can be done either using oAuth protocol or sessionId header. In order to keep this article simple and understandable, I’ve used the sessionId mechanism for authentication purpose.
 

Testing SOAP Web Services

First of all, let’s focus on the SOAP based web services. There are multiple tools and engine available to help testing SOAP web services, but for this article I’ve used SoapUI, which is a renowned and commonly used web service testing tool. If already not installed, download the latest version of soapUI from http://www.soapui.org/
 

Testing SOAP API

The latest version of SalesForce provides 40+ services to create, retrieve, update or delete system and custom objects. It also provide security related services for login, logout etc.
To test the enterprise services, follow below listed steps:
  1. Download latest enterprise wsdl file by navigating to setup -> develop -> API -> Generate Enterprise WSDL, as shown below


  2. Now create a new project in SoapUI and provide the downloaded enterprise wsdl file




  3. As mentioned in the start of this tutorial, we are using sessionId header for authentication, we have to invoke ‘login’ as the first service. The output of this service will provide us sessionId, which can then be used to invoke other services. Along with this, for enterprise services, you also need to capture the server URL to call further services. The SOAP request for login service should look this (note that I’ve remove the unnecessary soap headers)

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:enterprise.soap.sforce.com">
       <soapenv:Header>
       </soapenv:Header>
       <soapenv:Body>
          <urn:login>
             <urn:username>salesforce_username</urn:username>
             <urn:password>password</urn:password>
          </urn:login>
       </soapenv:Body>
    </soapenv:Envelope>
     
  4. From the response xml, copy the serverURL value and create a new end point in SoapUI as shown below. Use this end point to invoke all other services




  5. Also, copy session ID from the SOAP response of login service. This would be required to be set in soap header of all future calls
     
  6. Now let’s call another service “describeSObject”. To accomplish that, open the soap request, set the session ID, remove all other header tags, and change the end point at the top. The request should look similar to this

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:enterprise.soap.sforce.com">
       <soapenv:Header>
          <urn:SessionHeader>        
      <urn:sessionId>00DL00000028rzP!ARQAQAx4kjpx.OuCJnJnpAxH7kAiaJ8AQSOvJty1V4A1VNElxXzrIr.u8Q54cewnLxLzFQmj9xELwinlshhXpE.rgVog72uR</urn:sessionId>
          </urn:SessionHeader>
       </soapenv:Header>
       <soapenv:Body>
          <urn:describeSObject>
             <urn:sObjectType>Account</urn:sObjectType>
          </urn:describeSObject>
       </soapenv:Body>
    </soapenv:Envelope>
After invocation, the response will render all information related with Account SObject.
Similarly you can call all other services from enterprise WSDL. You should know the values of required parameters in the service. As example, to retrieve a specific SObject, you must know the ID of the same.

Testing Apex SOAP Web Services

Along with standard services, user can also write custom SOAP based services in Apex. Testing Apex Web Services is comparatively easier. The steps are mentioned below
  1. Download the Apex WSDL from sales force. For this navigate to setup -> Develop -> Apex Classes. Now navigate to the Apex web service class and click on WSDL link, as shown below
  2. Now in SoapUI, add a new wsdl to the already created project (above) and locate the downloaded Apex web service WSDL
  3. Again you need to login to Sales Force first, using login service and copy the sessionID to call any Apex web service. But note that in this case, you shouldn’t change the end point and use the one mentioned in your Apex WSDL only. Hence escape the step #4 mentioned above in testing SOAP API

Testing SOAP Web Services Using Java Client

This section explains steps to write a simple java client to test SalesForce SOAP web services (both enterprise and Apex)

Testing SOAP API

  1. The first step to write java client for testing SF SOAP API, is to generate the jar file corresponding to underlying wsdl. You can use wsdl tool provided by SalesForce to generate this jar file. This jar provides all objects, stubs and connection classes to call web services. In order to test SOAP API, you need to generate enterprise jar file, corresponding to enterprise wsdl. The steps for generating this jar file are given below
    Download force-wsc.jar (v27.0.0) from http://mvnrepository.com/artifact/com.force.api/force-wsc. Note that higher versions have some issues. I could work with version 27.0.0

    Download js.jar file from
    http://mvnrepository.com/artifact/rhino
  2. Now download the wsdl from SFDC for which jar file is to be generated. To download enterprise wsdl, navigate to setup -> Develop -> API. Click on link “Generate Enterprise WSDL, as shown below




    Run below command
    java -classpath force-wsc-27.0.0.jar;js-1.7R2.jar com.sforce.ws.tools.wsdlc enterprise.wsdl enterprise.jar
    This will output enterprise jar file.
     
  3. Create a new Java project in eclipse and add the jar generated in step 1 above, along with force-wsc-27.0.0.jar, in the project class path.
  4. Now you can write java code to call web services. A sample code is given below.



import java.io.FileNotFoundException;
import com.sforce.soap.enterprise.DescribeSObjectResult;
import com.sforce.soap.enterprise.EnterpriseConnection;
import com.sforce.ws.ConnectionException;
import com.sforce.ws.ConnectorConfig; 
public class TestEnterpriseWebServices {
   private final String authEndPoint = //End point as per wsdl
   private final String username = //SFDC user name
   private final String password = //Password
   public static void main(String[] args) throws Exception {
         TestEnterpriseWebServices ws = new TestEnterpriseWebServices();
         ws.testDescribeSObject();
   }    
    /**
     * This method uses the describeSObject service of SalesForce and print information regarding Account SObject.
     */
    private void testDescribeSObject() {
         try {
            ConnectorConfig config = new ConnectorConfig();
            config.setUsername(username);
            config.setPassword(password);
            config.setAuthEndpoint(authEndPoint);
            config.setTraceFile("traceLogs.txt");
            config.setTraceMessage(true);
            config.setPrettyPrintXml(true);
            EnterpriseConnection conn = new EnterpriseConnection(config);
            DescribeSObjectResult result = conn.describeSObject("Account");
            System.out.println(result.toString());
          } catch (ConnectionException ce) {
            ce.printStackTrace();
          } catch (FileNotFoundException fnfe) {
            fnfe.printStackTrace();
          }
    }
}


Testing Apex SOAP Web Services


Testing Apex web service is slightly tricky, as it require first calling login service of enterprise wsdl and copying the session ID
  1. Download the WSDL file of your custom Apex web service
  2. Generate the jar file as we did incase of enterprise wsdl. In this case the command wuld look like this: java -classpath force-wsc-27.0.0.jar;js-1.7R2.jar com.sforce.ws.tools.wsdlc TestAppexWebServiceProvider.wsdl TestAppexWebServiceProvider.jar

    Note that you would need both jar file (enterprise and TestAppexWebServiceProvider jar).
  3. In the above project created for enterprise services, you can add the apex related custom jar in class path
  4. Now write java code to call these services. Below is a sample code:
import java.io.FileNotFoundException;
import com.sforce.soap.TestAppexWebServiceProvider.Connector;
import com.sforce.soap.TestAppexWebServiceProvider.SoapConnection;
import com.sforce.soap.enterprise.EnterpriseConnection;
import com.sforce.ws.ConnectionException;
import com.sforce.ws.ConnectorConfig;
public class TestApexWebServices {   
   private final String authEndPoint = //End point as per wsdl
   private final String username = //SFDC user name
   private final String password = //Password 
      public static void main(String[] args) throws Exception {
            TestApexWebServices ws = new TestApexWebServices();
            ws.testApexWebservice(ws.getSessionId());
      }
      /**
       * Get the session ID.
       * @return
       */
    private String getSessionId() {    
        try {
          ConnectorConfig config = new ConnectorConfig();
          config.setUsername(username);
          config.setPassword(password);
          config.setAuthEndpoint(authEndPoint);
          config.setTraceFile("traceLogs.txt");
          config.setTraceMessage(true);
          config.setPrettyPrintXml(true);    
          EnterpriseConnection conn = new EnterpriseConnection(config);
          String sessionId = conn.getSessionHeader().getSessionId();
          System.out.println("New session Id:" + sessionId);
          return sessionId;
        } catch (ConnectionException ce) {
          ce.printStackTrace();
        } catch (FileNotFoundException fnfe) {
          fnfe.printStackTrace();
        }
        return null;
      }  
    private void testApexWebservice(String sessionId) throws Exception {
      SoapConnection conn = Connector.newConnection("","");
      conn.setSessionHeader(sessionId);
      String result = conn.hello("Hi this is me…");
      System.out.println(result);   
    }
}

Testing Rest Services


Along with SOAP, SalesForce also extensively support RESTful services as a powerful, convenient, and simple Web services API for interacting with Force.com platform. There are multiple tools and strategies available to test Rest services, including SoapUI Pro, browser specific tools (e.g. postman for chrome, Rest client for mozila firefox etc ). In this article I’ve used another simple tool called cURL. cURL is a light-weight utility for transforming data to URLs. It is a very convenient tool to test RestFul web services

Although cURL is pre-installed on many Linux and Mac systems, you can download it from http://curl.haxx.se/download.html. Better to download the installable version

As we know, the pre-step calling any service in SalesForce is to authenticate yourself. As already mentioned, we are using sessionID based authentication in this article. Hence the 1st step would be to generate sessionID. There are 2 ways to do this.

1. If you have the client ID and secret, you can use cURL to retrieve session ID for you:
curl https://.salesforce.com/services/oauth2/token -d "grant_type=password" -d "client_id=myclientid" -d "client_secret=myclientsecret" -d "username=mylogin@salesforce.com" -d "password=mypassword12345
 
2. Otherwise the simple step is to use SoapUI and call login service to retrieve sessionID as we did in case of SOAP based web services.

Now let’s start calling some available resources on your salesforce server
 To know all rest resources:
curl https:// [your_sub_domain].salesforce.com/services/data/v29.0/ -H "Authorization: Bearer [sessionID]" -H "X-PrettyPrint:1"
 
To know all sObjects of your organization:
curl https://[your_sub_domain].salesforce.com/services/data/v29.0/sobjects -H "Authorization: Bearer [sessionID]" -H "X-PrettyPrint:1"
 
To know brief about Account sObject:
curl https:// [your_sub_domain].salesforce.com/services/data/v29.0/sobjects/Account -H "Authorization: Bearer [sessionID]" -H "X-PrettyPrint:1"
 
Now let’s use JSON objects to send with request inorder to create some sObject.
Curl https:// [your_sub_domain].salesforce.com/services/data/v29.0/sobjects/Account -H "Authorization: Bearer [sessionID] " -H "X-PrettyPrint:1" -H "Content-Type: application/json" -d  "@[complete path to json file]"

Your JSON file should look like this:
{
          "Name" : "My Test Account"
}

The above Rest request would create a new Account in the system and the response should look like this:
{
         "id" : "",
         "errors" : [ ],
         "success" : true
}
 
In the above example, you could also use xml to send information. The xml would look like this:
<?xml version="1.0" encoding="UTF-8"?>
<Account>
      <Name>My Test Account</Name>
</Account>
 
And the command would be:
Curl https:// [your_sub_domain].salesforce.com/services/data/v29.0/sobjects/Account -H "Authorization: Bearer [sessionID] " -H "X-PrettyPrint:1" -H "Content-Type: application/xml" -d @[complete path to xml file]"
 

Testing Apex Rest Services


So far, in above section, we tested the inbuilt Rest services of SalesForce using cURL. Now we’ll cover testing Apex Rest Services here.
For this example, I’ve written a simple Apex Rest service

global with sharing class TestApexRestServiceProvider{
    @HttpGet
    global static String doGet() {
        RestRequest req = RestContext.request;
        RestResponse res = RestContext.response;
        String orgName = req.params.get('orgName');
        return 'Get Message : ' + orgName;
    }   
    @HttpPost
    global static String myPostMethod(String orgName) {
        RestRequest req = RestContext.request;
        RestResponse res = RestContext.response;   
        return 'Post Message : ' + orgName;
    } 
}
To test the get method, use this url:
curl https:// [your_sub_domain].salesforce.com/services/apexrest/MyRestRs?orgName=MyOrg -H "Authorization: Bearer [sessionId]”  -H "X-PrettyPrint:1"
And to test the post method:
Curl https:// [your_sub_domain].salesforce.com/services/apexrest/MyRestRs -H "Authorization: Bearer [sessionId]”  -H "X-PrettyPrint:1" -H "Content-Type: application/json" --data-binary @C:\Users\aarya\Desktop\test.json
Notice that in case of get, the request parameter is sent through url, which for post, its read from json file and sent as part of request body.

Conclusion

SalesForce support webservices as easy, convenient and powerful mechanism of communication. It supports both SOAP and Rest services. This articles shows how to use SoapUI and simple Java code to consume SOAP based services and cURL for Rest services. 

Reference




 

2 comments:

Eric Anand said...

Hello there,

Can I ask a question, how and where from do you find the Client ID and Secret ?

Thanks in Advance !

Whizdom Trainings said...

hi,we provide online training & video tutorial for soapui
for free videos refer
http://soapui-tutorial.com/soapui-tutorial/introduction-to-webservices/