Using the Salesforce REST API with Javascript (and jQuery) in Visualforce Pages using APEX

The Salesforce REST API can give you responses formatted in JSON. JSON would be great to use with javascript and jQuery in Visualforce pages, but I haven’t been able to do it directly (passing an Authorization token) so I did it with the help of an APEX controller.

To use the REST API you need to send requests to Salesforce endpoints, such as https://na1.salesforce.com/services/data/v20.0/sobjects/, but you need to pass an authorization token in the header of the request. This endpoint will list the available objects in your organization’s Salesforce data. In APEX, you can retrieve the Salesforce session id for the user you are using and this can be used when accessing the REST API.

When you are accessing the REST API, the ‘https://na1.salesforce.com/services/data/v20.0/’ part of the endpoint you access will not change so you can setup a Visualforce page that takes a query parameter with that portion of the endpoint. For this example, I’ve called that query parameter ‘action’.

Here’s the Visualforce page we will use to access the controller:

<apex:page controller="rest" action="{!retrieve}" contentType="text/plain; charset=utf-8">{!result}</apex:page>

We want the JSON formatted respose to be returned when calling a ‘getResult’ method and we want the action that’s run when visiting this page to be ‘retrieve’ (this is where we’ll call the Salesforce REST API). Here’s the shell of the APEX controller:

public class rest {	
 
	public rest() {
		//constructor, let's grab the session token here
	}
 
	public void retrieve() {
		//we'll call the REST API here
	}
 
	//getter method to return JSON result
	public string getResult() {
		return this.result;
	}
}

Adding in the code to:

  1. grab the session id
  2. add special handling for the query request
  3. make the call to the REST API

We’ll end up with:

public class rest {	
	private PageReference page;
	private string action;
	private string session;
	private string result;
 
	public rest() {
		//constructor, let's grab the session token here
		session = userInfo.getSessionId();
 
		page = ApexPages.currentPage();
		this.action = page.getParameters().get('action');
		if (action == null) action = '';
 
		integer q = action.indexOf('query/?q=');
 
		if(q >= 0) {
			string qs = action.substring(q + 9);
			action = action.substring(0, q + 9);
 
			action += EncodingUtil.urlEncode(qs, 'UTF-8');
		}
	}
 
	public void retrieve() {
		//we'll call the REST API here
		http h = new http();
 
		httprequest req = new httprequest();
		//note that 'na1' may be different for your organization
		req.setEndpoint('https://na1.salesforce.com/services/data/v20.0/' + action);
		req.setMethod('GET');
		req.setHeader('Authorization', 'OAuth ' + session);
		req.setTimeout(60000);
 
		httpresponse res = h.send(req);
 
		result = res.getBody();
	}
 
	//getter method to return JSON result
	public string getResult() {
		return this.result;
	}
}

With that, you should be able to start calling the REST API using javascript and jQuery on a Visualforce page. Here’s how you could call it using jQuery:

?View Code JAVASCRIPT
jQuery.getJSON("https://na1.visual.force.com/apex/rest?core.apexpages.devmode.url=1&action=query/?q=SELECT Name FROM Account", function(response) {
     console.log(response);
});
This entry was posted in APEX, API, Governor Limits, JavaScript, jQuery, REST, Salesforce. Bookmark the permalink.

10 Responses to Using the Salesforce REST API with Javascript (and jQuery) in Visualforce Pages using APEX

  1. Pingback: Using the Salesforce REST API with Javascript (and jQuery) in …

  2. Alex says:

    Nice post, exactly what I was looking – a simple example about calling REST from your VF page.
    I have a comment, or maybe it’s a question: Doesn’t open up your page/controller to some crazy unpredictableness? That is, can’t someone modify your javascript like this to get sensitive information?

    jQuery.getJSON(“https://na1.visual.force.com/apex/rest?core.apexpages.devmode.url=1&action=query/?q=SELECT Name, Credit_Card_Numbers__c, Address__c FROM Contact”, function(response) { console.log(response); });

    • Ben says:

      So the calls will be using the session id for the running user, so whatever that user has access to they would be able to query. It wouldn’t give them access to data they didn’t already have access to though.

  3. Jordan says:

    Hey Ben,

    Great How-To, really put’s REST in VF in context for me, I just was curious if you had a quick question about determining endpoints:

    You refer to ‘na1.visual.force.com’ – in the Controller and in the jQuery URL.

    I’m on a different Salesforce instance, na3 or na7 for example – do I also have to define my custom ‘Remote Access URL’ from within ‘Setup->Security->Remote Site Settings’ to access my VF Pages remotely?

  4. Zach says:

    Why use the REST API when you can use JavaScript Remoting? Advantages of Remoting:
    1. Faster responses than REST API (in my tests, consistently 50-100% faster)
    2. Also returns JSON
    3. No need to rely on an admin to specify a Remote Site.
    4. Better for ISV’s, because in Remoting calls you can specify namespace-agnostic object and field names (i.e. “SELECT MyCustomField__c FROM MyObject__c” as opposed to having to use “SELECT myNamespace__MyCustomField__c FROM myNamespace__MyObject__c”), whereas the REST API requires fully-qualified names

    To implement such a solution, you could create a library of static remoting functions that do all that the REST API does (and more, if you want…), and put them in a controller for a “wrapper” component, i.e.

    with controller code:


    global with sharing class RemotingToolkit {

    // Perform a with-sharing, JS Remoting query
    @RemoteAction
    global static SObject[] query(String soql) {

    List L = new List();
    try {
    L = Database.query(soql);
    } catch (Exception e) {
    return null;
    }
    return L;
    }

    }

    In your VF pages, implement this “wrapper” component and its available Remoting methods like this:

    // Obtain a unique reference to jQuery
    $j = jQuery.noConflict();

    $j(document).ready(function() {

    var queryString = "SELECT Name FROM Account";

    RemotingToolkit.query(queryString,function(result,event) {
    if (event.status) {
    tabulateResults(result,$j('#resultsDiv'));
    } else {
    alert('Remoting call failed');
    }
    });
    });

    // Params:
    // (1) JSON response array of SObject records
    // (2) jQuery object into which to inject a table-ized version of the JSON
    function tabulateResults(records,tableObject) {

    var tableString = ''
    + ''
    + '' + tableObject.attr('title') + ''
    + 'IndexName'
    + '';
    $j.each(records, function(index,record) {
    tableString += '' + index + '' + record.Name + '';
    });
    tableString += '';

    tableObject.html(tableString);
    }

    However, if you really need the REST API (i.e. if you’re doing mobile dev), here’s an alternative: instead of having to rely on a separate VF page as an AJAX endpoint, you could create a JS toolkit, such as this one endorsed by Developer Force: Force.com JavaScript REST Toolkit. The toolkit provides easy wrapper methods for quickly getting at all of the other functions provided by the REST API, i.e. metadata describes, CRUD operations, etc. In practice, it looks very similar to Ben’s example, only you’re including an additional JS file at page load time, as opposed to having to build a separate controller and VF page to act as an AJAX endpoint:

    // Get a reference to jQuery that we can work with
    $j = jQuery.noConflict();

    // Get an instance of the REST API client and set the session ID
    var client = new forcetk.Client();
    client.setSessionToken('{!$Api.Session_ID}');

    client.query("SELECT Name FROM Account LIMIT 1", function(response){
    $j('#accountname').html(response.records[0].Name);
    });

    The first account I see is .

    • Ben says:

      Hi Zach,

      Using remoting is definitely something I do sometimes instead of going through the API – you are just limited to the stricter governor limits (50,000 results for queries). I did not realize you could return JSON without modifying the Lists of sObjects you get back from the Database.query calls (this is one thing I wanted to avoid having to do)?

      The ajax toolkit works very similarly I believe, just using a Salesforce built proxy (serves the same function as the visualforce page and controller in this example).

      Cheers,
      Ben

  5. Mike says:

    Does anyone know of using the ISeries RPGLE to interact with SalesForce using REST or SOAP ?

  6. Luke says:

    I am well aware of jQuery’s ability to call and interpret JSON, but I was wandering if this would work on a hybrid mobile app with Salesforce?
    The reason for wanting to use REST API over remoting, is because the REST API has some advantages with Chatter.

    Since we are not using Visualforce but we are using Apex, I would like to know if the Apex instance will still recognize the user when communicating from the external HTML5.

    Presumably, when using oAuth in the hybrid application, this will notify the Salesforce instance of that user being logged in.

  7. Atul says:

    Hi Ben,

    I am trying to post chatter feed on a record from apex I followed your approach but I am getting error which says [{"message":"Session expired or invalid","errorCode":"INVALID_SESSION_ID"}] when passed the userInfo.getSessionID() in header. Can you please help me with this ?

    Appreciate your feedback.

    Atul

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>