Appcelerator Arrow – Salesforce Composite Connector Example

Arrow Salesforce

One main feature of Appcelerator Arrow is the ability to create mobile-optimized APIs without writing any code. This reduces the burden on IT to create mobile-specific versions of back end web services, while at the same time providing a means for mobile developers to easily expose data in a format that is tailored specifically for the app at hand. This results in an app that is highly performant since data reduction, orchestration and aggregation do not need to be performed within the app itself.

This blog post will describe how to use Arrow’s Salesforce and Composite connectors to retrieve data from Salesforce in a fashion optimal for mobile.

Read more about Arrow here.

Use Case

A common use case is a Master/Detail view. For example, in Salesforce, you can view a list of Accounts as follows:


Notice that the Master list view above is showing all the accounts but only displays certain fields. On a mobile device, you will likely show only 2-3 fields in the Master list view as shown below (name, phone and type):


When you select an account to view its details in Salesforce, you will see the account detail view below with all the related information (opportunities, contacts, cases, …):


For the mobile app, you would never try to display all this data on a small screen device. Instead you would build according to your most common use cases for your users. For example, your use case may be to display several details about the account (phone, web, priority, SLA, address, …) and then a list of all opportunities for that account as follows:


So, now that we have designed the information architecture of our app, we can start to think about how we can retrieve the data to populate these screens. There are several viable approaches:

(a) Approach A
Retrieve a list of accounts and all the fields required for the Master View and the Detail View
When the user selects an account, retrieve a list of Opportunities for the selected account

The disadvantage of this approach is that if the user only selects one or two accounts, you have already downloaded all the account details for all of the accounts, even though you only needed the account details for one or two accounts

(b) Approach B
Retrieve a list of accounts and only the fields required for the Master View
When the user selects an account, retrieve a list of Opportunities for the selected account and the fields required for the account detail

Without Arrow, the mobile developer would need to study the Salesforce Search and Query Language (SOQL and SOSL) to retrieve Salesforce data via web service calls on the device (

This is where Arrow really shines. Regardless of which approach you decide to take for data retrieval, described above, Arrow Builder makes it very easy to create these mobile-optimized APIs without needed to learn SOQL and SOSL or write any code.

In this example, we will implement Approach B.

Arrow Builder

Make sure your Arrow environment is setup properly by following the instructions at the following link:!/guide/Arrow_Quick_Start

Create a new Arrow project and install the salesforce and composite connectors using the following commands:

  appc login
  appc new
  appc install connector/appc.salesforce
  appc install connector/appc.composite

Edit the appc.salesforce.default.js file with your salesforce url, username, password and security token

run the application locally, using the following command:

appc run

Launch a browser and enter the following url:

You will now be in the Arrow Admin which provides the means to create models and APIs as well as test out your API.


Create the Account API for the Master View

Click on Build and create a new model called AccountMaster. We will be reducing the default Salesforce Account model which exposes all of the Account fields.


Click Next.

On the Model Fields section, click on the View Fields button to see all the base Account Fields, select the Name, Type and Phone fields and click the Add Fields button



Click Next.

On the next screen (Optional Properties) click on Next.

On the next screen press the Save Model button.

You will be automatically taken the API Docs tab for your newly created APIs where you will see all of the APIs that were automatically created for your new Model, AccountMaster. On this screen you can also test out your APIs.

GET /api/accountmaster

POST /api/accountmaster

GET /api/accountmaster/query

GET /api/accountmaster/:id

PUT /api/accountmaster/:id

PUT /api/accountmaster/findAndModify

GET /api/accountmaster/count

POST /api/accountmaster/upsert

GET /api/accountmaster/distinct

DELETE /api/accountmaster/:id

DELETE /api/accountmaster


Pressing Find will return all accounts:

  "success": true,
  "request-id": "49e771e9-d414-4baa-83ae-c22ac6c68d74",
  "key": "accountmasters",
  "accountmasters": [
      "id": "001i000000PscewAAB",
      "Name": "GenePoint",
      "Type": "Customer - Channel",
      "Phone": "(650) 867-3450"
      "id": "001i000000Pscf6AAB",
      "Name": "United Oil & Gas Corp.",
      "Type": "Customer - Direct",
      "Phone": "(212) 842-5500"
      "id": "001i000000Pscf7AAB",
      "Name": "sForce",
      "Phone": "(415) 901-7000"
      "id": "001i000000PI81bAAD",
      "Name": "Test from Mobile - Leor"

As you can see above, we are also getting an id field which corresponds to the Account Id. This will be used for the call to retrieve the Account Details and Opportunity API, which we will create next.

Create the AccountWithOpps API for the Detail View

Create a new Model called AccountDetail as we did above but add all the fields required for the Account Detail screen

Create an Opportunity Model as we did above with the Name, Stage, Amount and Close Date fields. We will need to add one more field to the Opportunity model, AccountId, in order to only retrieve the opportunities for a given Account.


Now we can create the AccountWithOpps model which will be a composite model (join):


Click Next. In the Model Fields screen, select “Map new field to entire model” and add the AccountDetail as the Source Model and name the field “Account”. Data type is Object. Press Add Field.



Now add the Opportunity as the next Field Source Model, name the Field “Opportunity” and Data Type is Array since we want to retrieve all opportunities for a given Account.



Click Next.

Now, we need to fill in the Join Properties. Enter AccountDetail as the Parent Model. Select id as the Join Field and Outer join as the Join Type. Enter Opportunity as the Child Model and select AccountId as the Join Property and press the Add Join button.



Click Next and Next again and Save Model.

You will be taken to the API Docs tab for the AccountWithOpps API:


Scroll down to the GET /api/accountwithopps/:idand enter an account id and press find:


Inspecting the JSON reply you can see the following:

  "success": true,
  "request-id": "c3f4cead-78cf-4c63-90a0-e5cac2f822aa",
  "key": "accountwithopp",
  "accountwithopp": {
    "id": "001i000000Pscf4AAB",
    "Account": {
      "id": "001i000000Pscf4AAB",
      "Name": "Express Logistics and Transport",
      "Type": "Customer - Channel",
      "BillingAddress": {
        "city": "Portland",
        "country": null,
        "countryCode": null,
        "latitude": null,
        "longitude": null,
        "postalCode": null,
        "state": "OR",
        "stateCode": null,
        "street": "620 SW 5th Avenue Suite 400\nPortland, Oregon 97204\nUnited States"
      "ShippingStreet": "620 SW 5th Avenue Suite 400\nPortland, Oregon 97204\nUnited States",
      "Phone": "(503) 421-7800",
      "Website": "www.expressl&",
      "Industry": "Transportation"
    "Opportunity": [
        "id": "006i000000A6YYtAAN",
        "AccountId": "001i000000Pscf4AAB",
        "Name": "Express Logistics Portable Truck Generators",
        "StageName": "Value Proposition",
        "Amount": 80000,
        "CloseDate": "2011-09-11T00:00:00.000Z"
        "id": "006i000000A6YZ3AAN",
        "AccountId": "001i000000Pscf4AAB",
        "Name": "Express Logistics SLA",
        "StageName": "Perception Analysis",
        "Amount": 120000,
        "CloseDate": "2011-09-11T00:00:00.000Z"
        "id": "006i000000A6YYkAAN",
        "AccountId": "001i000000Pscf4AAB",
        "Name": "Express Logistics Standby Generator",
        "StageName": "Closed Won",
        "Amount": 220000,
        "CloseDate": "2011-09-11T00:00:00.000Z"

In the reply above, you see the AccountDetail information along with an array of Opportunities related to that account.

Go ahead and publish your application using the “appc publish” command and start building mobile apps.

Now you have mobile-optimized APIs that can be used in your Appcelerator app, web app and with any client that can consume REST APIs.


In this example, we saw how Arrow can enable mobile app developers to create highly specific and mobile-optimized APIs for a variety of data architectures without writing a single line of code. The composite connector enabled us to create an API that returned Account and Opportunity data in one API. This will results in a highly performant app since we are retrieving the data exactly how we need it in the app.

The models and a sample JSON reply for this sample project can be found here:

Read more about Arrow here:!/guide/Appcelerator_Arrow