Using Apex REST Resources

To support Apex REST resources, Mobile SDK provides two classes: Force.ApexRestObject and Force.ApexRestObjectCollection. These classes subclass Force.RemoteObject and Force.RemoteObjectCollection, respectively, and can talk to a REST API that you have created using Apex REST.

Force.ApexRestObject

Force.ApexRestObject is similar to Force.SObject. Instead of an sobjectType, Force.ApexRestObject requires the Apex REST resource path relative to services/apexrest. For example, if your full resource path is services/apexrest/simpleAccount/*, you specify only /simpleAccount/*. Force.ApexRestObject also expects you to specify the name of your ID field if it's different from "Id".

Example

Let's assume you’ve created an Apex REST resource called "simple account," which is just an account with two fields: accountId and accountName.

1@RestResource(urlMapping='/simpleAccount/*')
2  global with sharing class SimpleAccountResource {
3      static String getIdFromURI() {
4          RestRequest req = RestContext.request;
5          return req.requestURI.substring(req.requestURI.lastIndexOf('/')+1);
6      }
7      
8      @HttpGet global static Map<String, String> doGet() {
9          String id = getIdFromURI();
10          Account acc = [select Id, Name from Account 
11                         where Id = :id];
12          return new Map<String, String>{
13              'accountId'=>acc.Id, 'accountName'=>acc.Name};
14      }
15  
16      @HttpPost global static Map<String, String> 
17          doPost(String accountName) {
18              Account acc = new Account(Name=accountName);
19              insert acc;
20              return new Map<String, String>{
21                  'accountId'=>acc.Id, 'accountName'=>acc.Name};
22      }
23  
24      @HttpPatch global static Map<String, String> 
25          doPatch(String accountName) {
26              String id = getIdFromURI();
27              Account acc = [select Id from Account 
28                                 where Id = :id];
29              acc.Name = accountName;
30              update acc;
31              return new Map<String, String>{
32                  'accountId'=>acc.Id, 'accountName'=>acc.Name};
33      }
34  
35      @HttpDelete global static void doDelete() {
36          String id = getIdFromURI();
37          Account acc = [select Id from Account where Id = :id];
38          delete acc;
39          RestContext.response.statusCode = 204;
40      }
41  }

With Mobile Sync, you do the following to create a "simple account".

1var SimpleAccount = Force.ApexRestObject.extend(
2    {apexRestPath:"/simpleAccount", 
3      idAttribute:"accountId", 
4        fieldlist:["accountId", "accountName"]});
5var acc = new SimpleAccount({accountName:"MyFirstAccount"});
6acc.save();

You can update that "simple account".

1acc.set("accountName", "MyFirstAccountUpdated");
2acc.save(null, {fieldlist:["accountName"]); 
3// our apex patch endpoint only expects accountName

You can fetch another "simple account".

1var acc2 = new SimpleAccount({accountId:"<valid id>"})
2acc.fetch();

You can delete a "simple account".

1acc.destroy();

In Mobile Sync calls such as fetch(), save(), and destroy(), you typically pass an options parameter that defines success and error callback functions. For example:

1acc.destroy({success:function(){alert("delete succeeded");}});

Note

Force.ApexRestObjectCollection

Force.ApexRestObjectCollection is similar to Force.SObjectCollection. The config you specify for fetching doesn't support SOQL, SOSL, or MRU. Instead, it expects the Apex REST resource path, relative to services/apexrest. For example, if your full resource path is services/apexrest/simpleAccount/*, you specify only /simpleAccount/*.

You can also pass parameters for the query string if your endpoint supports them. The Apex REST endpoint is expected to return a response in this format:
1{   totalSize: <number of records returned>
2   records: <all fetched records>
3   nextRecordsUrl: <url to get next records or null> 
4}

Example

Let's assume you’ve created an Apex REST resource called "simple accounts". It returns "simple accounts" that match a given name.

1@RestResource(urlMapping='/simpleAccounts/*')
2global with sharing class SimpleAccountsResource {
3    @HttpGet global static SimpleAccountsList doGet() {
4        String namePattern = 
5            RestContext.request.params.get('namePattern');
6        List<SimpleAccount> records = new List<SimpleAccount>();
7        for (SObject sobj : Database.query(
8            'select Id, Name from Account 
9             where Name like \'' + namePattern + '\'')) {  
10                 Account acc = (Account) sobj;
11	          records.add(new 
12                     SimpleAccount(acc.Id, acc.Name));
13        }
14        return new SimpleAccountsList(records.size(), records);
15    }
16    
17    global class SimpleAccountsList {
18        global Integer totalSize;
19        global List<SimpleAccount> records;
20        
21        global SimpleAccountsList(Integer totalSize, 
22            List<SimpleAccount> records) {
23                this.totalSize = totalSize;
24                this.records = records;
25        }
26    }
27    
28    global class SimpleAccount {
29        global String accountId;
30        global String accountName;
31        
32        global SimpleAccount(String accountId, String accountName) 
33        {
34            this.accountId = accountId;
35            this.accountName = accountName;
36        }
37    }
38}

With Mobile Sync, you do the following to fetch a list of "simple account" records.

1var getSimple = function() {
2    console.log("## Trying fetch with apex rest end point");
3    var config = {
4        apexRestPath:"/simpleAccounts", 
5        params:{namePattern:accountNamePrefix + "%"}
6    }
7    return Force.fetchApexRestObjectsFromServer(config);
8}