Wednesday, July 24, 2013

SalesForce.com Authorised Application using Apache HttpComponents

This article describes how to create a basic authorised application that will query the SalesForce.com API without the need for logging in to your account
  1. Register a SalesForce.com remote application
    • Create a SalesForce.com Developer account - http://developer.force.com/
    • On connection to the salesforce.com api, you must provide your password and the security token combined as a string
    • Log into your account and click App Setup(in the menu on the left) -> Create -> Apps
    • Under "Connected Apps", click New
    • Enter the Connected App Name, Connected API Name and Contact Email (note - it's recommended to not use spaces in the App and API names)
    • Under OAuth Settings. select "Enable OAuth Settings"
    • Enter the Callback URL - in an OAuth application this is the URL the application will return to after authentication, which will not be needed here, but the value cannot be blank
    • Select "Access and manage your data (api)" in the "Available OAuth Scopes" and add it to the "Selected OAuth Scopes"
    • Click Save
    • In the application description page that opens, note the Consumer Key, and Consumer Key values (you will need to click "Click to reveal" to see it)
    • In the user dashboard, click Personal Setup -> My Personal Information in the menu on the left, then Reset My Security Token.
    • Your security token will be not be displayed on screen, and will be sent to the email address associated with the salesforce.com account
      • e.g. for password "myPassword" and security token "mySecurityToken" the connection is authorised with the string "myPasswordmySecurityToken"

  2. Develop application in Eclipse
    • Create a new Java project
    • Add the following jar files:
      • From the apache http components project  - http://hc.apache.org/ - you will need the following jar files
        • httpclient
        • httpcore
    • The following code snippet will open a connection to the SalesForce API and return a JSON document
      • Replace the values in angle brackets with the appropriate values from your setup
      • String accessToken = null;
        String instanceUrl = null;
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost("https://login.salesforce.com/services/oauth2/token");
        // prepare the parameters
        ArrayList postParameters = new ArrayList();
        postParameters.add(new BasicNameValuePair("grant_type", "password"));
        postParameters.add(new BasicNameValuePair("client_id", {your application client id}));
        postParameters.add(new BasicNameValuePair("client_secret", {your application client secret}));
        postParameters.add(new BasicNameValuePair("username", {your salesforce.com username}));
        postParameters.add(new BasicNameValuePair("password", {your salesforce.com password + your salesforce.com security token}));
        // prepare the form, and set the encoding
        UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(postParameters);
        urlEncodedFormEntity.setContentEncoding("UTF-8");
        httpPost.setEntity(urlEncodedFormEntity);
        // place the right content type for the form
        httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
        // execute the request to get the tokens
        HttpResponse httpResponse = httpClient.execute(httpPost);
        int statusCode = httpResponse.getStatusLine().getStatusCode();
        if (statusCode == HttpStatus.SC_OK) {
            ObjectMapper objMapper = new ObjectMapper();
            InputStreamReader inputStreamReader = new InputStreamReader(httpResponse.getEntity().getContent(), "UTF-8");
            JsonNode rootNode = objMapper.readTree(inputStreamReader);
            accessToken = rootNode.get("access_token").asText();
            instanceUrl = rootNode.get("instance_url").asText();
        }
        System.out.println("AccessToken: " + accessToken);
        System.out.println("instanceUrl: " + instanceUrl);
  3. Query the SalesForce API
    • The instanceUrl is the salesforce.com server that all subsequent queries must be sent to, and the access token must be set as the "Authorization" header in all subsequent requests
    • One of the simplest requests is to retrieve the details for the customer accounts associated with your salesforce.com account, this list can be seen in the Account header on your dashboard
    • Use the following code snippet to request the list of accounts and store the JSON string in the accounts String object
      • URIBuilder uriBuilder = new URIBuilder(instanceUrl + "/services/data/v28.0/query");
        uriBuilder.addParameter("q", "SELECT Name, Id, BillingStreet, BillingCity, Phone, Website from Account LIMIT 100");
        String accounts = null;
        HttpGet httpGet = new HttpGet(uriBuilder.build());
        httpGet.addHeader("Authorization", "OAuth " + accessToken);
        try {
            httpResponse = httpClient.execute(httpGet);
            if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
             InputStreamReader inputStreamReader = new InputStreamReader(httpResponse.getEntity().getContent(), "UTF-8");
             accounts = objMapper.readTree(inputStreamReader).toString();
            }
        } finally {
             httpGet.releaseConnection();
         }
        System.out.println(accounts);
While these snippets will work perfectly well in a command line application, in a web application, it is prudent to persist the instance url and access token in the user's HttpSession object.