đź“Ł Attention Salesforce Certified Trailblazers! Link your Trailhead and Webassessor accounts and maintain your credentials by December 14th. Learn more.
close
trailhead

Access Salesforce Data via REST APIs

Learning Objectives

After completing this unit, you’ll be able to:

  • Instantiate a REST request with the RestClient class
  • Issue an asynchronous REST request with the RestClient and RestRequest classes
  • Receive and process a REST response with the RestResponse class

Using REST APIs

When you’re ready to access Salesforce data in your app, you call Salesforce REST APIs. REST APIs, as a rule, are low-level enough that developers can access them manually through rudimentary network calls. However, you don’t have to do that—you have Mobile SDK to handle the messy grunt work for you.

Here’s a summary of the classes that handle REST API calls. All these classes live in the com.salesforce.androidsdk.rest package.

  • ClientManager—Serves as a factory for RestClient instances. It also handles account logins and handshakes with the Salesforce server.
  • RestClient—Handles protocol for sending REST API requests to the Salesforce server.

    Don’t directly create instances of RestClient. Instead, call the ClientManager.getRestClient() method.

  • RestRequest—Formats REST API requests from the data your app provides. Also serves as a factory for instances of itself.

    Don’t directly create instances of RestRequest. Instead, call an appropriate RestRequest static getter function such as RestRequest.getRequestForCreate().

  • RestResponse—Formats the response content in the requested format, returns the formatted response to your app, and closes the content stream. The RestRequest class creates instances of RestResponse and returns them to your app through your implementation of the RestClient.AsyncRequestCallback interface.

Here’s a an animated diagram that shows this flow in action.

REST API runtime flow (Android)
  1. The app calls a static method on the RestRequest class to create a configured RestRequest instance.
  2. The app passes the new RestRequest instance and an instance of the AsyncRequestCallback interface to the RestClient.sendAsync() method.
  3. Mobile SDK sends the REST request presented in the RestRequest object to the Salesforce cloud service.
  4. Salesforce processes the request and returns a JSON response to the app.
  5. Mobile SDK packages the JSON response in a new RestResponse object.
  6. Mobile SDK passes the new RestResponse object to the app’s AsyncRequestCallback implementation for consumption.

Still awake? Let’s move beyond the conceptual level and see this information at work in the real world of your app.

The sendRequest() Method

Your MainActivity class sends REST requests and then uses the REST responses to populate its list view. Let’s dive back into the MainActivity code to trace this flow.
  1. In Android Studio’s Project window, expand app | java | com.mytrail.android.
  2. Double-click MainActivity.
  3. Find the onFetchContactsClick method. Notice that this tiny method calls a sendRequest() method with a SOQL statement.
    public void onFetchContactsClick(View v) throws UnsupportedEncodingException {
           sendRequest("SELECT Name FROM Contact");
    } 
  4. Right-click “sendRequest” and then select Go To | Implementation(s). Turns out that sendRequest() is a private method in your MainActivity class. That’s cool that it’s yours, because we’re going to change it later!
The sendRequest() method is where you see the Mobile SDK REST classes at work. The major players here are:
  • client—A private, class-scoped instance of RestClient. This object is instantiated automatically during app initialization
  • restRequest—A new RestRequest instance
  • RestRequest.getRequestForQuery()—A static RestRequest factory method that creates the RestRequest instance
  • AsyncRequestCallback—Your app’s implementation of the REST response callback interface

Creating the REST Request

In sendRequest(), the RestRequest.getRequestForQuery() factory method takes a SOQL string and wraps it in a RestRequest object:
RestRequest restRequest = 
    RestRequest.getRequestForQuery(
        getString(R.string.api_version), soql); 
The advantage of using RestRequest factory methods is that the generated object is network-ready—it already knows the HTTP settings that the Salesforce server expects.

Sending the REST Request

To send the request to Salesforce, you pass the RestRequest object to the RestClient.sendAsync() method:
client.sendAsync(restRequest, new AsyncRequestCallback()
    { 
    ...
Mobile SDK code creates the client object for you while it’s initializing your activity. The second parameter, of type AsyncRequestCallback, is an instance of a virtual interface that’s designed to receive REST responses. In this example, AsyncRequestCallback is implemented and instantiated inline.

The “async” prefix keeps showing up here. That’s got to mean something important, right? When you send a request asynchronously, it means that your app’s code doesn’t pause to wait for the response. When the response does arrive, Mobile SDK calls one of your callback methods, and the app briefly suspends whatever’s going on to process the response. You’re required to send requests asynchronously when your code’s execution is occurring on the main (UI) thread.

Capturing and Processing the REST Response

When Salesforce returns the REST response, the RestClient object forwards it to your AsyncRequestCallback implementation. In the AsyncRequestCallback interface, you define how your app handles the REST response from Salesforce. You handle successful REST responses in the onSuccess() method:
@Override
public void onSuccess(RestRequest request,
    final RestResponse result) {
    result.consumeQuietly(); // consume before going back to main thread
    runOnUiThread(new Runnable() {
        @Override
        public void run() { 
            try {
                listAdapter.clear();
                JSONArray records = 
                    result.asJSONObject().getJSONArray("records");
                for (int i = 0; i < records.length(); i++) {
                    listAdapter.add(
                        records.getJSONObject(i).getString("Name"));
                } 
             } catch (Exception e) {
                 onError(e);
             }
        }
    });
}
and you recover gracefully from failed requests in the onError() method:
@Override
public void onError(Exception exception)
{
    runOnUiThread((new Runnable() {
        @Override
        public void run() {
            Toast.makeText(MainActivity.this,
            MainActivity.this.getString(
                SalesforceSDKManager.getInstance().
                    getSalesforceR().stringGenericError(),
                exception.toString()),
            Toast.LENGTH_LONG).show();
        }
    });
}
Notice that the REST response arrives in JSON format, so it’s pretty easy for code-writing humans to parse. If the query succeeds, the app extracts Name field values to populate the UI list view. If the query fails, the app displays a toast containing an error message.
retargeting