About Me

The Force Times

The Force Times

I am a Salesforce Evangelist working at Suyati Technologies Pvt Ltd at Kochi(Kerala, India). I spend most of my free time experimenting with the Force.com platform.

View Full Profile →

Categories

Calendar

November 2014
M T W T F S S
« Apr    
 12
3456789
10111213141516
17181920212223
24252627282930

AJAX Proxy for VisualForce

Before getting into what exactly is an AJAX Proxy, if you were a web developer, let me ask whether you had come across an error message as below in either of your browsers Console window:

XMLHttpRequest cannot load https://datamarket.accesscontrol.windows.net/v2/OAuth2-13. Origin https://c.ap1.visual.force.com is not allowed by Access-Control-Allow-Origin.

If no, then I am definitely sure you have never tried invoking any external web services from JavaScript. Now, what is this error all about ? Today, almost all the web browsers enforces a security rule, that says, “A script or an application is not allowed to make a connection to any web server except to the one the web page originally came from.” In a more technical way, this is termed as ‘Same Origin Policy‘. As per the W3C, the Same Origin Policy is defined as 

The Same Origin Policy permits scripts running on pages originating from the same site – a combination of scheme, hostname, and port number – to access each other's methods and properties with no specific restrictions, but prevents access to most methods and properties across pages on different sites. Same origin policy also applies to XMLHttpRequest.

Now, some of the most common uses cases where we tend to violate this rule is while making POST request to external OAuth endpoints, for receiving Access Tokens and Refresh Tokens. As in Force.com, these situations come very often where we are required to access services of external systems like Mass Email Providers, Language Translators, Google Services and so on.

There are a number of solutions to overcome this restriction but let me brief you about the most commonly used practice – set up a proxy on you web server . In this, the calls (XmlHTTPRequests) are primarily made to the web server proxy and it is this web server proxy that makes the POST requests to the external web service. The web server proxy in return passes the data returned by the external web service to the client application. So, now our browser will have nothing to object.

VisualForce provides an inbuilt AJAX proxy for developers to handle such situations. I will demonstrate the use of the same via a simple use case. The use case is creating a Translator Widget for Force.com. The Translator Widget uses the Microsoft Translator API for translating across languages.

All that you need for this widget is an account on the Windows Azure Marketplace and then subscribe to the Microsoft Translator API. The best part of the Microsoft Translator API is that it provides a limit of 2,000,000 characters/month at no cost. This certainly a very good number. I have also used some of the BootStrap to bring in good looking UI.

The complete source code of the VisualForce page that I had created has been made available for everyone via Github Gists.

Let me start of from the beginning. The first script tag is for the guest of the day ! Yes, for using the AJAX proxy that VisualForce provides. The second script tag is for the most beloved jQuery which is used by both us and the BootStrap. The third script tag and the following stylesheet is for the BootStrap. Both the jQuery and the BootStrap files are accessed via the CDNs(Content Delivery Networks) and I haven’t created them as Static Resources which would likely be the ideal choice. The last script is a JS file that I had created for actually creating the <li>…</li> tags. To display the from language list and the to language list, I had used <ul>…</ul> tags. Rather than creating the <li>…</li> tags for the UL tags then and there within the HTML, I opted to that through code. My main intention to do so was to reduce the size of the HTML code that would displayed via the GIST. You can peek at the same at here.

Now to the JS. Let me brief about the working of the Microsoft Translator API. In order to translate a piece of content via the Translator API, one must make a GET request to the Translation endpoint with the UTF-8 encoded text or the content to be translated, from language and the to language as Query String parameters. It would look like the one given below.

https://api.microsofttranslator.com/v2/Http.svc/translate?text=encodeURIComponent(<TEXT-TO-TRANSLATE>) + &from=+ <FROM-LANGUAGE> +&to=+ <TO-LANGUAGE>

No, that is not all. To authorize yourselves to Microsoft Translator API, you must also pass an Access Token as a request header while making the above translation request.

The process of fetching Access Token from Microsoft OAuth endpoint is pretty simple. The OAuth endpoint is https://datamarket.accesscontrol.windows.net/v2/OAuth2-13. The various parameters that are to be passed to get the Access Token for accessing the Microsoft Translator API are tabulated as below.

Parameter Name Value
grant_type client_credentials
client_id encodeURIComponent(<YOUR-CLIENT-ID>)
client_secret encodeURIComponent(<YOUR-CLIENT-SECRET>)
scope http://api.microsofttranslator.com

These parameters are to be passed in through the request body and it would look like the one given below.

grant_type=client_credentials&client_id='+encodeURIComponent(<YOUR-CLIENT-ID>)+'&client_secret='+encodeURIComponent(<YOUR-CLIENT-SECRET>)+'&scope=http://api.microsofttranslator.com'; 

Now comes the role of our AJAX proxy. We will be making the above POST request for getting the Access Token via the AJAX proxy.

The AJAX proxy provided by VisualForce is a part of the AJAX Toolkit. We can access it using remoteFunction defined in the connection.js. We can define any HTTP verbs in remoteFunction, for example HTTP GET or POST. To use the AJAX proxy, you must register all external services in the Salesforce user interface, in Your Name | Setup | Security Controls | Remote Site Settings

Now that we have received the Access Token, lets see how can we make a GET request via the AJAX proxy. The GET request that we would be making will be in order to get the Translated content.

That is all folks! Now just watch a screen capture of the same and see how it works.

Run Your SOAP Web Services Asynchronously

Salesforce provides the AJAX toolkit which includes incorporated support for invoking Apex SOAP Web Service methods from JavaScript. The only requirement to do so is to include the following JS files:

<script src="/soap/ajax/27.0/connection.js" type="text/javascript"></script>
<script src="/soap/ajax/27.0/apex.js" type="text/javascript"></script>

For example, consider the following Apex SOAP Web Service.

global class UtilityMethods {
 webService static String findContactName(String email) {
  Contact c = 
   [SELECT ID, Name, Email FROM Contact WHERE Email =: email];
  return c.Name;
 }
}

By using the following JavaScript code:

var name = sforce.apex.execute
 (
   ‘UtilityMethods’,
   ‘findContactName’,
   {
     email:’deepak@salesforce.com’
   }
 );

That was pretty easy. But there is a drawback for the sforce.apex.execute method. It isn’t asynchronous. And if you were to execute a much more time consuming job within your SOAP Web Service unlike the above, may be invoking an external web service, then a synchronous call may cause your browser tab or Visualforce page to be frozen for a while. In other words, if you had invoked that service from a button click, then you would be able to notice that the button remains as though it is sunken(visually) or clicked for a short time. Yes, the Visualforce page has become unresponsive. This is certainly leaving you Visualforce page less usable.

Don’t worry. There is a way out. We can invoke this SOAP Web Service using the

jQuery.ajax()

method. I will explain it using a small use case. If you had browsed over my previous blog post about creating a ‘Google URL Shortening’ widget on your side bar, then probably you would be familiar that it too had a similar situation where a SOAP Web Service which implemented the Google URL Shortening service was called from JavaScript via the sforce.apex.execute method on a button click. Since calling an external Web Service is a time consuming process, an AJAX call is definitely required if you want your web pages to become responsive.

The APEX class that implements the Google URL Shortening service is as follows:

https://gist.github.com/Deepak-K-Anand/bf8f79b3aa63c193ad6e

At first, we have to observe as to how actually are the requests being made to the SOAP Web Service. These include the Request URL, Data, SOAPAction and the Content-Type. To monitor that, I had used the Console provided by the Chrome Web Browser. Firstly, create a Visualforce page named “ObserveSOAPCalls” with HTML as below.

<apex:page>
 <script src="/soap/ajax/27.0/connection.js" type="text/javascript"/>
 <script src="/soap/ajax/27.0/apex.js" type="text/javascript"/>
 <script>
   sforce.connection.sessionId = '{!GETSESSIONID()}';
 </script>
</apex:page>

Open the Visualforce page in you Chrome Web Browser. You can do that by just typing ‘https://ap1.salesforce.com/apex/ObserveSOAPCalls’ in you Address bar. Press F12 to open the Console.

Execute the following in the Console window.

sforce.apex.execute('GoogleUrlShortener','shortenUrl',{longUrl:'https://c.ap1.visual.force.com/apex/ObserveSOAPCalls'});

Open the Network tab and click on GoogleUrlShortener.

Chrome Console

Chrome Console

Headers

Headers

From the above Headers, we can identify the following important parameters:

Header Value
Request URL services/Soap/package/GoogleUrlShortener
Request Method POST
Content-Type text/xml; charset=UTF-8
SOAPAction “”

The other important parameter is the Request Payload.

Request Body

Request Body

Don’t close the Console. Just after the Preview tab there is the Response tab which will show the response from the Web Service. The response will be an XML document.

Response

Response

Using these, we can construct our $.ajax(…) method. The {!GETSESSIONID()} will return the current Session ID.

var requestBody =
<se:Envelope xmlns:se="http://schemas.xmlsoap.org/soap/envelope/"><se:Header xmlns:sfns="http://soap.sforce.com/schemas/package/GoogleUrlShortener"><sfns:SessionHeader><sessionId>{!GETSESSIONID()}</sessionId></sfns:SessionHeader></se:Header><se:Body><shortenUrl xmlns="http://soap.sforce.com/schemas/package/GoogleUrlShortener"><longUrl> <YOUR-LONG-URL-HERE> </longUrl></shortenUrl></se:Body></se:Envelope>

$.ajax(
 {
  url : '../services/Soap/package/GoogleUrlShortener',
  type: 'POST',
  data: requestBody,
  headers:
  {
   "SOAPAction" :'""',
   "Content-Type":"text/xml; charset=UTF-8"
  },
  success: function(data, textStatus, jqXHR){
    alert($(data).find('result').text());
  },
  error:function(jqXHR, textStatus, errorThrown){
  } 
 }
);

The argument data will contain the XML response from the Web Service. That’s it. Now you will no longer need those initial script tags for apex.js and connection.js to be included in your Visualforce page and enjoy making responsive Visualforce pages.

Delete Button for List Views

I have had many occasions where I really wanted a ‘Delete’ button on my List Views so that I could select all the records that were to be deleted and then just click the ‘Delete’ button. This post will explain how to create a Delete button for the List Views of any Custom Object.

Let’s begin by inspecting the HTML source of our List Views. For example, let’s consider the List View of the Lead. I will now go ahead assuming that you are using either Chrome or Firefox (with Firebug) as your web browser. Right-click anywhere on the page and select Inspect Element. If you are using Chrome, click on the Search icon at bottom of the Inspect Element Window and point the cursor to the checkbox corresponding to a record on the List View. You will able to see the HTML source of the checkbox element in the Inspect Window. For eg:

<input id="00Q9000000DTLS8" value="00Q9000000DTLS8" title="Bair, Betty" type="checkbox" name="ids">
List View Screenshot

List View Screenshot

The value field of this checkbox carries the unique 15 digit Salesforce ID for the corresponding record and the name field carries a value – ‘ids’. Now firstly, we have to fetch all the checkboxes from the page whose name attribute contains ids and those of which are checked and then save the data in the value attribute to an array. Once we get the list of IDs of those records which are to be deleted, we just need to execute a DELETE operation on the list of IDs.

If you are clear with that, let’s start to write the JavaScript code that will be executed when our Delete button will be clicked. Don’t worry, we haven’t yet created the button, but let’s start with the coding first.

{!REQUIRESCRIPT('https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js')}
{!REQUIRESCRIPT('/soap/ajax/26.0/connection.js')}
{!REQUIRESCRIPT('/soap/ajax/26.0/apex.js')}

Firstly, add these three lines in order to include three JavaScript files. The first one is the jQuery library which we will use to fetch the selected checkboxes on our page and the second and the third are standard Salesforce JS files that we will use to execute the DELETE command on the fetched record IDs.

Now, let’s add some variable declarations and the JS code that will scan for all the selected checkboxes on the page and save the value attribute into an array.

var selectedRecords = new Array();
var userConsent;
var delResult;
$(document).ready(
 function() 
 {
   $("input:checkbox[name=ids]:checked").each(
     function() 
     {
       selectedRecords.push($(this).val());
     }
   );
 }
);

Wow! That was a really small piece of code using jQuery which otherwise would have resulted in a large code written in pure JavaScript to perform the traversing of DOM elements. jQuery takes care of all that complexities and abstracts everything for us.

And finally, there comes the code for performing the DELETE.

if(selectedRecords.length<1)
 alert('Please Select at Least One Row !');
else
{
 userConsent = confirm(
  selectedRecords.length + 
  ' Record(s) will be Deleted. Are You Sure to Continue ? ');
 if(userConsent == true)
 {
  sforce.connection.sessionId = '{!GETSESSIONID()}';
  delResult = 
    sforce.connection.deleteIds(selectedRecords);
  if (delResult[0].getBoolean("success"))
  {
   alert('The Record(s) were Deleted Successfully.'); 
   window.location.reload(); 
  }
  else
   alert(
    'The Record(s) Could Not be Deleted. Error Message: '+
    delResult[0].errors.message);
 } 
}

If no checkboxes were selected, show a message box saying ‘Please Select at Least One Row !’. If there are some selected checkboxes, then we need an approval for deletion from the user. That’s done using the confirm method in JavaScript. If the user says, a YES to go ahead with the deletion, the code to delete the records will be executed. The sforce is a Standard Salesforce JavaScript Object that provides us with the CRUD operations on records and much more. Now, to perform the DELETE, firstly, we initialize the sessionId property with the current session ID so that all requests made via the sforce stands authorized. Once that is done, we can call the deleteIds(…) method to DELETE the records. The deleteIds(…) method expects an array of record IDs as the arguement. The deleteIds(…) method returns a JSON response containing the results of the DELETE operation.

Now, let’s create a Delete button and add the same to the List View. Let me go ahead with case of Leads for now. Go to Your Name → Setup. Under the App Setup section on the Force.com Sidebar, go to, Customize → Leads → Buttons and Links. Click New on the Custom Buttons and Links section. Type Delete as the Label and also Delete as the Name too. Select List Button as the Display Type. Select Execute JavaScript as the Behavior and OnClick JavaScript as the Content Source. Copy and paste the whole JavaScript that we had written into the input pane and click Check Syntax. You will get ‘No syntax errors in merge fields or functions.’ provided that you did not mess up with the code.

Let’s add this button to the Search Layouts of the Lead object. Go to Your Name → Setup. Under the App Setup section on the Force.com Sidebar, go to, Customize → Leads → Search Layouts. Click on the Edit next to the Leads List View. Under the Custom Buttons, move the Delete item from Available Buttons list to the Selected Buttons list. Click Save.

Now go to the Leads tab. Select the All view and click Go to find your Delete button. Go ahead and test it!

A Nice Little Gadget on Your Force.com Sidebar

In one of my previous blog post I had explained about the Integration of Google Drive into Force.com. When we upload a file to Google Drive and request for a shared URL, they usually return a very lengthy one for example https://docs.google.com/file/d/0Bwy2aaLW1FGta1paYVYyVlh3cnc/edit. Yes, it would have been easy if we had a URL Shortener on the Force.com Sidebar that would shorten long URLs. This blog post is all about creating a Google URL Shortener gadget and placing the same on the Sidebar.

On 14 December 2009, Google announced a service called Google URL Shortener at goo.gl, which originally was only available for use through Google products. The Google URL Shortener at goo.gl is a service that takes long URLs and squeezes them into fewer characters to make a link that is easier to share, tweet, or email to friends. Google also provides the APIs which allows us to integrate the URL Shortening Service into any of our Custom Web pages. Now, let’s see how we can integrate the same into Force.com.

At first I assume that you will have a G-Mail ID so that we can log on to Google APIs Console. If you are visiting the Google APIs Console for the first time, then first thing that it will ask you is to whether to create an API Project. No doubt and no hesitations go ahead and create one. Once when we successfully create a new API Project, we would land on the All Services tab. Scroll down and look for URL Shortener API. Switch it ON and you will love to see the figure 1000K requests/day. That’s plenty. Now, click on API Access link below the Services link. This opens to the API Access tab. In the Simple API Access section, you will notice an API Key. All the services provided by Google must be authorized before we actually use them. Some of them require an OAuth 2.0 authentication like the Google Drive API while others just require the API key for e.g., the Google URL Shortener API.

The URL Shortener API is quite simple and you find all the resources at https://developers.google.com/url-shortener/. I know you will be lazy to read all those things and that’s the main reason that you came here. Good, don’t worry let’s learn it in a much enthusiastic way. First of all, visit the Google API explorer at https://developers.google.com/apis-explorer/#s/urlshortener/v1/ in order to see the different services that are included in the Google URL Shortener API. You will be able to see three main services:

  • urlshortener.url.get
  • urlshortener.url.insert
  • urlshortener.url.list

It’s the second one that we are interested in i.e., urlshortener.url.insert. Click on the same. You would see two labels: fields and Request body. Forget about fields and let’s move with Request body. Click in the Text Box besides the Request body label, and you would notice that a Drop Down appears asking for the property. Select longUrl as we are going to give a lengthy URL which has to be shortened. Copy the URL from the Address bar of your browser and paste it there and click Execute. Scroll down to see the Request section to know how actually the request was send and to which endpoint. And further below, you would notice the Response section displaying the response from the Service endpoint.

Google APIs Explorer

Google APIs Explorer

The requests are made as POST requests to the

https://www.googleapis.com/urlshortener/v1/url?key={YOUR_API_KEY}

with a key parameter in the Query String which takes the API Key.  The Content Type is application/json and that’s quite apparent when you see it in the Request body. Now let’s look at the response. The response is again in JSON format and there will be three key-value pairs in the response. The id field is the one that carries the Short URL. Well, we are done with configurations and a whole round of experimentation with the service. That’s all that we can do through ‘Point & Click’. Now comes the role for the developer inside you. We have to start coding!!!

Let’s first write an APEX class that would make the POST requests to the Google URL Shortener Service and fetch the Short URLs.

global class GoogleUrlShortener
{
 webservice static string shortenUrl(string longUrl)
 {
  Http http = new Http();
  HttpRequest httpReq = new HttpRequest();
  HttpResponse httpRes = new HttpResponse();
  String body='';

  httpReq.setMethod('POST');
  httpReq.setHeader('Content-Type', 'application/json');
  httpReq.setEndpoint(
  ‘https://www.googleapis.com/urlshortener/v1/url?key=' + {YOUR_API_KEY});

  body = '{\"longUrl\": \"' + longUrl + '\"}';

  httpReq.setHeader(
    'Content-Length', 
    String.valueOf(body.length()));
  httpReq.setBody(body);

  try{
   httpRes = http.send(httpReq);
   String shortUrl = parseJSON(httpRes.getBody(), 'id'); 
   return shortUrl;
  }
  catch(Exception e){
   System.debug(
     'Class:GoogleUrlShortener;' +
     'Method:shortenUrl;' +  
     'Message:‘+e.getMessage());
   return 'ERROR'; 
  }
 }

 private static string parseJSON(String jsonText, String node)
 {
  JSONParser parser = null;
  parser = JSON.createParser(jsonText);
  while (parser.nextToken() != null)
  {
   if(parser.getText()==node)
   {
    parser.nextToken();
    return parser.getText();
   } 
  }
  return 'ERROR';
 } 
}

That’s a really simple class and I expect you would have grasped it in a single go! Well, now let’s create a VisualForce page.

<apex:page id="pgGoogleUrlShortener" sidebar="false" showChat="false" showHeader="false" standardStylesheets="true">
 <html>
  <head>
   <title></title>
   <script src="/soap/ajax/26.0/connection.js" type="text/javascript"></script>
   <script src="/soap/ajax/26.0/apex.js" type="text/javascript"></script> 
   <style type="text/css">
          body{
                background-color: transparent;
              }
   </style>
   <script> 
    function shortenUrl(){
        sforce.connection.sessionId = 
          '{!$Api.Session_Id}';
        var longUrl = 
          document.getElementById('long-url').value;
        var shortUrl = 
            sforce.apex.execute(
               'GoogleUrlShortener', 
               'shortenUrl', 
               {longUrl: longUrl}
            );
        document.getElementById('short-url').innerHTML = 
          shortUrl;
    }
   </script>
  </head>
  <body> 
   <h2>Paste your long URL here:</h2><br/>
   <input 
         id="long-url" 
         type="text" 
         value="" 
         placeholder="
           http://blogs.developerforce.com/tech-pubs/2012/12/the-spring-13-preview-release-notes-are-out.html"/>
         <br/>
   <input 
         type="button" 
         class="sf-button" 
         value="Shorten Url" 
         onClick=" shortenUrl();"/>
   <br/>
   <div id="short-url"></div>
  </body>
 </html>
</apex:page>

I bet you, the few lines that you would have been lost were those scripts. The sforce object belongs to the Standard JavaScript Library provided by Salesforce that allows us to execute Apex in Ajax. The sforce.apex.execute method allows us to execute any WebService methods written in Apex through JavaScript. This was the main reason behind exposing the shortenUrl method written in GoogleUrlShortener Apex class as a webservice. The sforce.apex.execute method expects three arguments i.e., the Class Name, the Method Name and the Parameters. We have now created an Apex Class and a VisualForce page that invokes the method in the class to fetch a the Short URL. Now let’s see how we can place the VisualForce page on the Sidebar.

Go to Your Name → Setup  Customize  Home  Home Page Components. Create a New Custom Component of type HTML Area. Select the Narrow (Left) Column as the Component Position. At the rightmost end of the Formatting Controls area, check the Show HTML checkbox. And now is the hack!!! We will now create a IFRAME that will load our VisualForce page.

IFRAME

IFRAME

That’s it and now click Save. Now go to Your Name   Setup   Customize   Home   Home Page Layouts. Edit the Default layout. You will observe that under the Select Narrow Components to Show section, the Google Url Shortener has been listed. Ensure that it is checked. Also to make sure that we would see our Custom Sidebar Component on all pages, go to Your Name   Setup   Customize   User Interface. In the Sidebar section, make sure that Show Custom Sidebar Components on All Pages option is checked. Well, now just refresh and go to any of the Tabs to see our gadget on the Force.com Sidebar.

Google URL Shortener Gadget

Google URL Shortener Gadget

Client Side Geocoding from Force.com

Geocoding is the process of converting addresses (like “1818 Greenfield Ave, Los Angeles, CA, United States”) into geographic coordinates (like latitude 34.048052 and longitude -118.440382), which we can use to place markers or position the map. Google Maps API provides extensive libraries in JavaScript to display maps on your custom web pages as well as to perform geocoding. You can find all the resources at https://developers.google.com/maps/documentation/javascript/. The Google Maps API Family provides two approaches to geocoding:

  • Client-side geocoding, which is executed in the browser, generally in response to user action.
  • HTTP server-side geocoding, which allows your server to directly query Google’s servers for geocodes.

Here is a sample of client-side geocoding which takes an address, geocodes it, and then displays the latitude and longitude values.

geocoder = new google.maps.Geocoder(); 
geocoder.geocode( 
 { 
 'address': 
    ‘1818 Greenfield Ave, Los Angeles, CA, United States’ 
 }, 
 function(results, status) 
 { 
  if (status == google.maps.GeocoderStatus.OK) 
  { 
   var message = 
    ‘Latitude: ‘ + results[0].geometry.location.lat()+ 
    ‘Longitude: ‘ + results[0].geometry.location.lng(); 
    alert(message); 
  } 
 } 
);

Here is an example of using Apex to do a server-side geocoding request.

HttpResponse res = null;
Http http = new Http();
HttpRequest req = new HttpRequest();
String address;
String jsonresp;
address = 
  '1818 Greenfield Ave, Los Angeles, CA, United States';
req.setMethod('POST'); 
req.setEndpoint('https://maps.googleapis.com/maps/api/geocode/json?address=' + EncodingUtil.urlEncode(address, 'UTF-8') + '&sensor=false');
res = http.send(req)
jsonresp = res.getBody();

Server-side geocoding through the Geocoding Web Service has a quota of 2,500 requests per IP per day, so all requests in one day count against the quota. Client-side geocoding through the browser is rate limited per map session, so the geocoding is distributed across all your users and scales with your user base. All the apps that run on a Salesforce server instance (say cs14, cs16, na2 etc.) share the same IP Address. For example let there be two apps say A and B running on the cs14 instance using the Google Geocoding Service. If the app A sends 2,500 requests for Geocoding, then the quota for that day for the IP of cs14 instance will be reached. Now, if the app B sends a geocoding request on the same day, it will be responded with the error code OVER_QUERY_LIMIT even though the app B did not make even a single request. Now, the only way to overcome this is to perform a Client-Side geocoding. Let’s see how we can do it through a small use case.

“Update the Latitude and Longitude fields of a Lead, Account or a Contact if any Address Related fields are changed.”

This use case can be handled by writing an Apex Trigger(after update) which checks for changes in the Address related fields (MailingStreet, MailingCity, MailingState, MailingPostalCode and MailingCountry) and if there is a change, then invoke the Google Geocoding Service to get the new values for Latitude and Longitude and update the fields with newly retrieved values. Since the Apex Code is compiled and is executed on your Salesforce instance server, this will in turn be a Server-side Geocoding request. And in the case of our App B, it will not be able to Geocode as the Google’s Geocoding Service has been exhausted for the day.

This situation can be handled by the Client Side Geocoding method since Client-side geocoding through the browser is rate limited per map session, so the geocoding is distributed across all your users and scales with your user base. Let’s take the Contact case for now.

  1. Add a new picklist field named Mapping Status to the Contact sObject. The values for this field will be Located, Not Located Yet, Problem with Address and Google Exhausted.
  2. Create a Workflow rule say ‘Reset Lead Mapping Status’ with an Evaluation Criteria – ‘Evaluate the rule when a record is created, and every time it’s edited’.
  3. The Rule Criteria will be

    OR
    (
         ISCHANGED(MailingStreet),
         ISCHANGED(MailingCity),
         ISCHANGED(MailingState),
         ISCHANGED(MailingPostalCode),
         ISCHANGED(MailingCountry)
    )

  4. Configure a Field Update say ‘Set Contact Mapping Status to Not Located Yet’ as a Workflow Action to the above workflow rule. This field update must be on the Contact sObject and the field to be updated will be the Mapping Status field of the Contact sObject. The New Field Value will be ‘Not Located Yet’.
  5. Activate the Workflow rule.

Now whenever the user changes any address related fields, the workflow rule will be evaluated and the Mapping Status field will be reset to ‘Not Located Yet’. We are now half done. Let’s move to the other half. Before moving to the second half, I expect that you will have some fundamental knowledge in VisualForce and Apex in Ajax. In case if you don’t, never hesitate to look ahead. It’s not at all that tough. Being a developer you can easily get into it.

1. Create a VisualForce page.

 <apex:page 
           standardController="Contact"
           showChat="false" 
           sidebar="false" 
           showHeader="false" 
           standardStylesheets="false">
 </apex:page>

Setting the standardController=”Contact” will allows us to drag and drop this VisualForce page on to the Standard Page layout of the Contact sObject.

2. Add the following script tags.

 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"/>
 <script src="https://maps.googleapis.com/maps/api/js?v=3.10&sensor=false"/>
 <script src="/soap/ajax/26.0/connection.js" type="text/javascript"/>
 <script src="/soap/ajax/26.0/apex.js" type="text/javascript"/>

The first js file is for some jQuery functions that we will use. The second js provides the methods for invoking the Google Geocoding Service. The third and the last are the Salesforce Standard JavaScript libraries which allow us to execute Apex through JavaScript.

3. Now let’s write some JavaScript(JS) methods.

var Contact = {};
function authorize()
{ sforce.connection.sessionId = '{!GETSESSIONID()}'; }
function getContactID() 
{ 
 var queryString = 
    window.parent.location.toString().split('/'); 
 Contact.ID = queryString[queryString.length-1];
}

The authorize() method sets the connection’s Session ID with the current Session ID so that all the methods invoked by the standard sforce object are authorized. The getContactID() gets the unique ID of the current Contact from the Query String. Here, we must notice that we are accessing window.parent.location and not window.location for the Query String. The reason is that VisualForce pages dragged into a Standard Page Layout will be rendered within an IFRAME and window.location would give us the Query String of the IFRAME.

function fetchContactRecord()
{
 result = sforce.connection.query('
          SELECT
                 ID,
                 MailingStreet,
                 MailingCity,  
                 MailingState,
                 MailingPostalCode,
                 MailingCountry,
                 Location__Latitude__s,
                 Location__Longitude__s,
                 Mapping_Status__c 
            FROM Contact 
            WHERE 
                 ID=\'' + Contact.ID + '\' AND 
                 Mapping_Status__c!=\'Located\'');
 records = result.getArray('records');
 if(records.length>0)
 {
  Contact.IsRecordAvailable = true;
  Contact.MailingStreet = records[0].MailingStreet;
  Contact.MailingCity = records[0].MailingCity;
  Contact.MailingState = records[0].MailingState;
  Contact.MailingPostalCode = 
    records[0].MailingPostalCode;
  Contact.MailingCountry = records[0].MailingCountry;
  Contact.MappingStatus = records[0].Mapping_Status__c;
 }
 else
  Contact.IsRecordAvailable = false;
}

The fetchContactRecord() will bring all the details necessary for Geocoding the address of the current Contact ensuring that the Contact has not been Geocoded yet. I assume that it’s clear from SOQL query.

Now let’s add some methods that will bring some beauty to the code.

Contact.isAddressAvailable = function(){
 if (
      this.MailingCountry!=’’ && 
      this.MailingPostalCode!=’’)
   return true;
 else
   return false; 
}
Contact.isMapped = function(){
 if ( 
      this.MappingStatus=='Located' || 
      this.MappingStatus=='Problem with Address'
    )
  return true;
 else
  return false; 
}
Contact.getCSVAddress = function(){
 if(this.isAddressAvailable())
 {
  return (
          this.MailingStreet +','+
          this.MailingCity +','+
          this.MailingState +','+ 
          this.MailingPostalCode +','+
          this.MailingCountry
         );
 }

 return 'error'; 
}

I think the JS code written above is very simple and needs no explanation. Now, let’s write the JS to perform the Geocoding. In fact Google has provided a very simple implementation for us to perform a Client Side Geocoding.

function getLatLng() 
{ 
 geocoder = new google.maps.Geocoder();  
 geocoder.geocode( 
 { 'address': Contact.getCSVAddress() }, 
 function(results, status) 
 { 
  if (status == google.maps.GeocoderStatus.OK) 
  { 
    Contact.Latitude  = 
      (results[0].geometry.location.lat()).toString();  
    Contact.Longitude = 
      (results[0].geometry.location.lng()).toString();  
    Contact.MappingStatus = 'Located'; 
  } 
  else if 
    ( 
     status == google.maps.GeocoderStatus.ZERO_RESULTS || 
     status == google.maps.GeocoderStatus.INVALID_REQUEST) 
  { 
   Contact.MappingStatus = 'Problem with Address'; 
  } 
  else if 
   (
    status == google.maps.GeocoderStatus.OVER_QUERY_LIMIT) 
  { 
   Contact.MappingStatus = 'Google Exhausted'; 
  }  
  updateContact(); 
 }); 
}

The google.maps.Geocoder() creates a new instance of the Google Maps Geocoder object. The geocoder object provides a method named geocode() to perform the Geocoding. It takes two arguments: the address to be Geocoded and the name of the callback function to be executed after the completion of the Geocoding process. Once the Geocoding is completed, the callback function (in this case I have given an anonymous function) is executed. The callback function checks for the status of the Geocoding process. If the status is OK (i.e., the Latitude and Longitude values corresponding to the address  were found by Google), we can save them to the Contact JavaScript object. Now, please don’t confuse this JavaScript object with the Salesforce Contact sObject. They are not related in any terms and the one in JS in our example is just an Object variable with some user defined properties like Latitude, Longitude, MappingStatus and some user defined functions like isMapped(), isAddressAvailable(), getCSVAddress() etc. Once the Geocoding is completed, let’s write a method that will Update the Contact sObject with the new Latitude and Longitude values.

function updateContact() 
{ 
 var mappedContact = new sforce.SObject('Contact__c');  

 mappedContact.Location__Latitude__s  = null; 
 mappedContact.Location__Longitude__s = null;  

 if(Contact.MappingStatus == 'Located') 
 { 
  mappedContact.Location__Latitude__s  = 
    Contact.Latitude; 
  mappedContact.Location__Longitude__s = 
    Contact.Longitude; 
 }  
 mappedContact.id = Contact.ID; 
 mappedContact.Mapping_Status__c = Contact.MappingStatus;

 result = sforce.connection.update([mappedContact]);  

 if(result[0].getBoolean('success')) 
 { 
  alert( 'The Contact\'s new Address has been located Successfully. Click \'OK\' to Refresh the Page.');  
  window.parent.location.reload(); 
 } 
}

The best thing that we can notice from the above code is that sforce JavaScript library provided by Salesforce is pretty awesome with some very good functions like the sforce.Sobject(), sforce.connection.update(), sforce.connection.query() etc. which makes the life of a developer very easy.

One thing that I would like to add is that Location field on the Contact sObject is a Geolocation field. The Geolocation field was introduced in Winter’13 release even though the same was available as a Pilot feature in the earlier releases. This field allows us to store Latitude and Longitude information either as Decimals or as Degrees. The Latitude field of a Geolocation field(say with name ‘Location’) can be accessed like Location__Latitude__s and so is Longitude. Now, the last thing that is left is the initiation of our JS methods i.e., to decide when should we begin the fetching process, geocoding and the record updating process. Let’s start the whole process chain when the DOM elements have been loaded successfully.

$(document).ready(
 function()
 {
  authorize();
  getContactID();
  fetchContactRecord();
  if(
     Contact.IsRecordAvailable && 
     !Contact.isMapped() &&
     Contact.isAddressAvailable())
  {
   getLatLng();
  }
 });

That’s it folks. We are done. Now, save your VisualForce page and drag it to the Standard Layout of a Contact sObject with zero values for both the width and height so that the VisualForce page stands invisible on the Detail Page. Just change any address fields to any other valid values and notice what happens.

Integration of Google Drive into Force.com


Google Drive is a file storage and synchronization service by Google    that was released on April 24, 2012. Rumors about Google Drive began circulating as early as March 2006. Unlike the other online storage services, the main feature that attracts one to the Google Drive is the Google Docs app. When a file is uploaded to the Google Drive, one can actually see the file contents via the Google Docs viewer without actually downloading it to your local machine. Thus, the files maintain their format identity when they reside on the Google Drive and do not become a mere data.

Google Drive gives all users 5 GB of cloud storage to start with and one can experiment with this free storage. Users need not sign in for another account to activate Google Drive. All the users who have a Gmail ID will also have access to their bucket of space on the Google Drive.

The first and foremost thing that you must have is a Gmail ID. I think that statement will not have any relevance today, as most of us have it and we usually sign in for Facebook with the Gmail IDs. Well, now you should create an API Project. In order to create the same, visit https://code.google.com/apis/console/. If you haven’t created one, the first thing that it will ask you is to create one. If that is done, go to the Services tab (I think it’s the one that opens automatically after the creation of a project) and you will be able to see a bunch of Google Services. In that list, switch the Drive API service to ‘ON’. The other best thing is that we have a limit of 500,000 requests per day which is really helpful. Three cheers to Google!!

As Google Drive comes as a part of your Gmail Account, it is obvious that we have to log in with our credentials before we can actually upload, download or view the files that reside in Google Drive bucket. Now, this can be handled by either of the following two ways. We can handover our credentials i.e., our password and our user id to the third party application which will be accessing the resources. This is certainly not a good idea. The second alternative is where the concept of OAuth 2.0 comes into play. OAuth 2.0 allows users to share specific data with any other third party apps (for example, contact lists) while keeping their usernames, passwords, and other information private.

If that’s clear and if you really don’t want to disclose your master password to any third party app, let’s get into some basics of OAuth 2.0 since our Salesforce App will be accessing the Google Drive via the OAuth tokens. Go to the API Access tab which is below the Services link and click on Create an OAuth 2.0 client ID….       This will open to a wizard with two screens where we have to enter the details about the application that is going to access our Google Drive bucket via our Gmail Account. In our case, it will be the app that we have created on the Force.com platform. Let’s fill up the Product name with say ‘HRForce’ and then click next. On the Step 2 of 2, select the Application Type as Web Application. For time being, let’s just skip the other details and proceed with ‘Create Client ID’. You can see that the Client ID and the Client Secret are created. We can also notice that two fields, Redirect URIs and JavaScript origins aren’t set with any values. Don’t worry; let’s forget about them for time sake and I assure I will get to it soon.

The next thing we are going to do is to understand how actually we can use the OAuth 2.0 tokens to authorize the desired account and to access the APIs. The best place to learn this is the ‘OAuth 2.0 Playground’. Don’t hesitate, it is not a developer manual or API reference, it’s just a playground. You can reach the same at https://developers.google.com/oauthplayground/. In the Step 1, select the API that you wish to Authorize. Let’s select https://www.googleapis.com/auth/drive and click on Authorize APIs. The page will be redirected to the Gmail’s login page(provided that you are not loggend in). Then, fill in your Gmail credentials and click Sign In. If the Sign In was successful, a new page is displayed which asks the account holder whether to allow access for the 3rd party app (Google OAuth 2.0 Playground) or not. No doubt, we have to allow and don’t panic, it’s not going to steal anything from your Google Drive bucket. But before that I would like you to peek at the URL.

https://accounts.google.com/o/oauth2/auth1?scope=https://www.googleapis.com/auth/drive2&response_type=code3&access_type=offline4&redirect_uri=https://developers.google.com/oauthplayground5&approval_prompt=force6&client_id=407408718192.apps.googleusercontent.com7&hl=en&from_login=1&as=-7352876500034384

1This is the URL to which we have to direct to from our Salesforce app in order to get a grant for access from the user. Now, this is done only for the first time and we need not do it every time when we access Google Drive.

2Scope(s) are those Google APIs that the app wants to access.

3Response Type with a value code indicates that Google should give me an Authorization Code in return after the approval process has been completed successfully.

4Access Type with a value offline is used if your application needs to refresh access tokens when the user is not present at the browser. This will result in your application obtaining a refresh token the first time your application exchanges an authorization code. Now, I am pretty sure that you will be confused with terms access token and refresh token. We will look into soon.

5Redirect Uri determines where the response is sent. The value of this parameter must exactly match one of the values registered in the APIs Console (including the http or https schemes, case, and trailing ‘/’). Yes, this something which we had actually skipped in that two-step wizard which involved the creation of the OAuth 2.0 Client ID. In our case we can actually configure this URL only if we are ready on the Salesforce side. Google redirects to this URL after a successful approval with the Authorization Code as a parameter in the Query String.

6Approval Prompt indicates if the user should be re-prompted for consent. If the value is force, then the user sees a consent page even if they have previously given consent to your application for a given set of scopes.

7Client ID is the one that we had created on the Google APIs Console while creating the OAuth 2.0 Client id.

Well, now let’s click Allow Access. You can observe that we are redirected back to our OAuth 2.0 Playground’s home screen. Look at the URL and you can notice that we have a parameter named code with a value. This value is the Authorization Code. This Authorization Code is then exchanged in order to receive an access token and a refresh token. Click on the Exchange authorization code for tokens. Both the Refresh Token and the Access Token will be fetched.

Access Token plays the role of the passwords. We can use the Access Token as a substitute for passwords in order to prove the identity and then access the Google API. These Access Tokens have a lifetime of 3600 seconds or 1 hour. Any access to the Google APIs with an expired access token will be denied. There comes the role of Refresh Tokens. The Refresh Tokens never expire and they can be used to retrieve new Access Tokens.

The most important thing that we have to keep in mind is that, on clicking the Exchange authorization code for tokens, a POST request is made. On the right hand side pane of the Playground, we can see that a POST has been made to /o/oauth2/token with host being accounts.google.com. In other words, a POST request is being made to https://accounts.google.com/o/oauth2/token with a message body containing information as below:

code=4%2FpnlSoZoIp0trg04KIW8gAFC6r099.kgQZqaF3M6kSgrKXntQAax0o1-_gdgI&redirect_uri=https%3A%2F%2Fdevelopers.google.com%2Foauthplayground&client_id=407408718192.apps.googleusercontent.com&scope=&client_secret=************&grant_type=authorization_code

The code parameter contains the Authorization Code and grant_type parameter has a value authorization_code. The response to this POST request is a JSON text containing the Access Token and the Refresh Token.

{
   "access_token":"ya29.AHES6ZQ1njBd9EMusvihjSxjZ_Z-JPLLqBDExAI3_IeTHLYQKzyZtw",
   "token_type":"Bearer",
   "expires_in":3600,
   "refresh_token":"1/fBbyP9Slezg3oibr5BdpkpgDrmVXS-op4y19fIzy4js"
}

If we want to refresh our expired Access Token, then we must make a POST request to the https://accounts.google.com/o/oauth2/token but with a different message body. The message body will contain the client_id and client_secret and will no longer have the code parameter. Instead of the redirect_uri parameter we will have a new parameter named refresh_token with the refresh token value and the grant_type will not have authorization_code as the value and rather it will take refresh_token as the value.

Thus we have received an Authorization Code, an Access Token and a Refresh Token from Google. Now, let’s move to the Force.com Platform. At first, as per the best practices, I suggest that we should create a Custom Settings which will keep the tokens. Let’s name it KeySafe. The entries in the KeySafe may include the Client ID, Client Secret, Authorization Code, Access Token and the Refresh Token. Also, we will maintain an another Custom Settings named Enpoint which will keep the different endpoints like the Scopes, Redirect URL, Authentication URL, Tokens URL and so on.

Endpoint Custom Settings

Endpoint Custom Settings

Key Safe Custom Settings

Key Safe Custom Settings

Now, we can write an Apex Class which will make the POST requests for getting the Access Token, Refresh Token and also make requests for new Access Tokens with a Refresh Token.

public class GoogleDrive
{
 private static Http http;
 private static HttpRequest httpReq;
 private static HttpResponse httpRes;
 private static void Initialize()
 {
  http = new Http ();
  httpReq = new HttpRequest();
  httpRes = new HttpResponse();
 }
 public static boolean getTokens(String tokenType)
 {
  String messageBody='';
  Initialize();
  httpReq.setMethod('POST');
  httpReq.setEndpoint(<Fetch the Google Token URL from EndPoint>);
  httpReq.setHeader('content-type', 
   'application/x-www-form-urlencoded');

  messageBody = 
  'client_id='+<Fetch Client ID from Key Safe>+ 
  '&client_secret='+<Fetch Client Secret from Key Safe>;

  if(tokenType=='ALL')
   messageBody = messageBody + 
   '&code='+<Fetch Authorization Code from Key Safe>+ 
   '&redirect_uri='+<Fetch Redirect URI from EndPoint>+ 
   '&grant_type='+'authorization_code';

  else if(tokenType=='ACCESS_TOKEN')
   messageBody = messageBody + 
   '&refresh_token='+<Fetch Refresh Token from Key Safe>+ 
   '&grant_type='+'refresh_token';

  httpReq.setHeader('Content-length', 
    String.valueOf(messageBody.length()));

  httpReq.setBody(messageBody);
  try
  {
   httpRes = http.send(httpReq);
   parseJSON(httpRes.getBody());
   return true;
  }
  catch(Exception ex)
  {
   System.debug('Class: GoogleDrive', 
   'Method: getTokens', 
   ex.getMessage());
   return false;
  }
 }    
 private static void parseJSON(String jsonText)
 {
  JSONParser parser = null;
  parser = JSON.createParser(jsonText);
  while (parser.nextToken() != null)
  {
   if(parser.getText()=='access_token')
   {
    parser.nextToken();
    <Save as Access Token into Key Safe>
   }
   if(parser.getText()=='refresh_token')
   {
    parser.nextToken();
    <Save as Refresh Token into Key Safe>
   }            
  }    
 }

Now, a question that can arise is what is Redirect URI and where should we set a value for the same. It’s quite certain that you will be having a doubt about the same as we had skipped that portion of setting the Redirect URIs and JavaScript origins in that two step wizard that we had come across while creating the API Project. In the implementation that I had done, I had made a Tab on the Force.com Platform called the Authentication which had two buttons namely, the ‘Authorize’ and ‘Get Tokens’.

Authentication Tab

Authentication Tab

When user clicks the Authorize button, the page is redirected to Google’s Login Page initially (provided that you have not logged in) and followed by Allow Access page. Once we click the Allow Access page, we will be redirected back to our Authentication tab with an additional Authorization Code in the Query String. We were redirected back because I had set my Redirect URI at the Google API Console to the address of my Authentication tab.

Now, when the user clicks the Get Tokens button, a server side POST is made with the Authorization Code that we received from the above step along with the other parameters which include the Client IDClient SecretGrant TypeRedirect URI and the Refresh Token. Now, don’t get confused. If you look at the Apex Class(written above) the parameters for getting a Refresh Token and Access Token varies. Both the Client ID and Client Secret are required regardless of whether we need an Access Token or a Refresh Token. Even though server side POSTs does not do any redirection, Google requires us to set the value for Redirect URI which is the same as that you had set from API Console.

Now, the last thing that is left to say is how can we upload a file to the Google Drive by authenticating ourselves using the Access Token that we have received. To do this, I had created a VisualForce page named Documents Uploader 

Documents Uploader Page

Documents Uploader Page

with following script tag :

<script type="text/javascript" src="https://apis.google.com/js/client.js"/>

Once we get the file from the user call the,

request = gapi.client.request( 
{ 
 'path'    : <The Path of the Shared Folder on Google Drive>,
 'method'  : 'POST', 
 'params'  : {'uploadType': 'multipart'}, 
 'headers' : 
  { 
   'Content-Type'  : 'multipart/mixed; boundary="' + <Boundary Seperator> + '"',
   'Authorization' : 'OAuth ' + <Fetch the Access Token from Key Safe>  },
 'body'    : <File Contents seperated by the Boundary Seperator> 
});

request.execute(<Name of Callback Function>);

In fact I had used the same script the was provided by Quickstart(https://developers.google.com/drive/quickstart-js) tutorial published by Google. The only addition that I had to add was the ‘OAuth ” term along with the Access Token in the Authorization header which otherwise Google has done using the Authorize(…) method. The Authorize(…) method provides us with an Access Token and when we use the Authorize(…) its not required by us to mention this additional Authorization header. The problem of using the Authorize(…) method is that it requires a User Grant every time after the Access Token expires which is not all User Friendly approach.

That’s it. We are done. I hope you would have had a brief understanding of the whole stuff. I know that a visual presentation of whole stuff can definitely bring the topic much closer to you. I hope I can come up with a recording demoing the whole stuff so that you can get a clear picture of how things really goes about. Also, you are welcome to post your ideas and views about this article. Do approach me for doubts or clarifications.

Certifications


Salesforce.com Certified Force.com Developer

Salesforce Certification | License 1279300 | February 2013


Microsoft Specialist(R): Programming in HTML5 with JavaScript and CSS3

Microsoft | License 9539089 | November 2012


Enter your email address to follow this blog and receive notifications of new posts by email.

Join 22 other followers

Blogs I Follow

Innovations on the Force.com Platform

The Enforcer.net

a force.com blog

Salesforce Developers Blogs

Innovations on the Force.com Platform

Bob Buzzard Blog

Innovations on the Force.com Platform

Jeff Douglas

Innovations on the Force.com Platform

Innovations on the Force.com Platform

ForceGuru

Innovations on the Force.com Platform

Innovations on the Force.com Platform

All About Async & Cloud

Your pit stop for Cloud & Parallelism

Follow

Get every new post delivered to your Inbox.