Expression-Backed Record Tutorial

The walk-through on this page will help you create your first expression-backed record. Expression-backed records differ from other types of record types in that they use web services as their source data.

Use the provided API to understand how the configurations work. Then, try it with your own data or API. Keep in mind, the final configurations will need to change to fit your data type's field names and types.

For this tutorial, you will be required to create several objects in your environment. If you do not have permissions to do so, speak with your system administrator. Also, you will need to create these object in an application. If you have a sandbox application available, you can build object in there. Similarly, you can follow the Application Building Tutorial and create object within that.

The content below assumes a basic familiarity with interfaces and focuses more on the specifics of configuring the data source and list view. Consider going through the Interface Tutorial and Process-Backed and Entity-Backed Record Tutorial. Additionally, Record Design and Create a Record Type pages provide more consideration and how-to examples related to record creation.

The content below also assumes that you have a basic familiarity with using APIs.

The r/SpaceX API

We will be using the r/SpaceX API. This is a freely available, open source API that uses JSON and doesn't require authentication.

You'll create the following design objects:

Don't worry - building an expression-backed record isn't rocket science!

Setup

Before creating the record type, we will need to create a Data Type, a Connected System, a Record List Source, and a Record View Source.

Create the Source Data Type

The first thing we will set up is the CDT for our Record Type. The CDT should contain fields that will come back from your source integrations. These will become the record fields that we can use in our record list, record views, and record actions. For this example, we will create two data types: SpaceX_Launch and SpaceX_Rocket.

First we will create the SpaceX_Rocket data type:

  1. In your test application, click on the New dropdown, and select Data Type.
    1. In the Create Data Type modal create the data type from scratch.
    2. Append :spacex to the end of the default namespace.
    3. Name the data type SpaceX_Rocket. Optionally add a description
    4. Click Create. The data type will open in a new tab.
  2. For each item below, add a New Field, and give the name and data type specified below.
    • rocket_id (Number (Integer))
    • rocket_name (Text)
    • rocket_type (Text)
  3. Click Save.

Once SpaceX_Rocket has been created, we can create the SpaceX_Launch data type:

  1. Click on the New dropdown, and select Data Type.
    1. In the Create Data Type modal create the data type from scratch.
    2. Append :spacex to the end of the default namespace.
    3. Name the data type SpaceX_Launch. Optionally add a description
    4. Click Create. The data type will open in a new tab.
  2. For each item below, add a New Field, and give the name and data type specified below.
    • flight_number (Number (Integer))
    • mission_name (Text)
    • launch_year (Text)
    • launch_date_utc (Date)
    • rocket (SpaceX_Rocket)
    • launch_success (Boolean)
    • details (Text)
  3. Click Save.

/xbr-tutorial-data-type

When creating your CDT, follow the order above. This will ensure the columns in your list view matches what's are presented later in this example.

Create the Connected System

Once our Data Types have been set up, the next thing we will set up is the connected system for this API. To create a connected system:

  1. Within an application in Appian Designer, click New and select Connected System.
  2. Select the HTTP connected system.
  3. In the Create Connected System modal, give the connected system the name r/SpaceX API.
    • Optionally, add a system logo and description.
  4. Set the base URL to https://api.spacexdata.com/v3/.
  5. Since this is an unauthenticated API, you can leave the Authentication dropdown set to None.
  6. Click Create.
  7. On the Review Connected System Security modal, set the Default permission level to Viewer and click Save.

/xbr-tutorial-connected-system

Configure the Record List Source

Now that our connected system is set up, we can create our Record List Source. First, we will create an integration, and then we will create an expression to wrap it.

Create an Integration for the Record List Source

The first integration we build will populate the record list. This integration should return a list of the objects that will map to the Data Type for your record type.

We will be using the launches endpoint to return an array of SpaceX launches.

  1. Within an application in Appian Designer, click New and select Integration.
  2. For Connected System, select the r/SpaceX API connected system.
  3. Set the integration Name to SpaceX_getAllLaunches.
    • Optionally, add a description.
  4. Under Save In, click Create New Rule Folder.
  5. Set the Folder Name to SpaceX Rules.
  6. Select Create. The integration will pop-up in a new tab.
  7. Set the Relative Path to launches. This will be appended to the Base URL of the connected system to form a URL of https://api.spacexdata.com/v3/launches. /xbr-tutorial-url-configuration
  8. At this point, we can click the Test Request button to see if we're on the right track. This should return a success message: /xbr-tutorial-url-success.png
  9. Under the success message, click Convert JSON to Appian value to convert this response body to an Appian dictionary.
  10. Save the integration.

Configure the Integration for Paging, Searching, and Filtering

The next thing we want to do is configure our integration to handle paging, searching, and filtering. These can be manifested in a number of ways, depending on the API. The r/SpaceX API uses query parameters.

In this tutorial, we will enable paging by using the offset, limit, sort, and order parameters. We will enable search to work using the rocket_name parameter. Finally, we will enable filtering by launch year and launch success, using the launch_year and launch_success parameters.

These query parameters have dynamic values, and should be configured as expressions.

  1. First, let's create our rule inputs. We will create a rule input called pagingInfo of type PagingInfo, a rule input called searchText of type Text, a rule input called launch_year of type Text, and a rule input called launch_success of type Boolean. /xbr-tutorial-rule-inputs
  2. Next, let's create our query parameters. We will populate their values using the rule inputs we just created.
  3. Configure the query parameters associated with paging. Make sure to configure Query Parameter values as expressions. Paging is often the most complicated parameter to configure. This is because APIs don't understand the PagingInfo type, and different APIs handle paging in different ways. See the r/SpaceX API documentation for details on their pagination parameters.
    • Set the offset parameter to ri!pagingInfo.startIndex - 1
    • Set the limit parameter to ri!pagingInfo.batchSize
    • Set the sort parameter to index(ri!pagingInfo.sort, "field", null)
    • Set the order parameter to if(index(ri!pagingInfo.sort, "ascending", null), "asc", "desc")
  4. To enable search, set the value for rocket_name to ri!searchText.
  5. To enable filtering, set the value for launch_year to ri!launch_year and the value for launch_success to ri!launch_success. /xbr-tutorial-query-parameters
  6. At this point, we can run some tests to ensure our integration is behaving as expected by clicking the Test Request button.
  7. Save the integration.

ri!searchText and any rule inputs being used for filtering can have null values. However, a configured expression-backed record will never have a null value for startIndex or batchSize. Therefore, test values should be set such that ri!pagingInfo.startIndex and ri!pagingInfo.batchSize are not null.

Create an Expression Rule for the Record List Source

Now that the integration which backs our record list is set, we need to create an expression to wrap it. This expression will act as the glue between the integration and the record type. It will call the integration and transform it into a DataSubset.

  1. Create a new expression rule and give it the name SpaceX_source_getAllLaunches
  2. Set the Save In folder to SpaceX Rules
  3. Give it the same rule inputs that our integration has: a rule input called pagingInfo of type PagingInfo, a rule input called searchText of type Text, a rule input called launch_year of type Text, and a rule input called launch_success of type Boolean.
  4. Configure the expression rule to to call our integration and return a datasubset.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
a!localVariables(
  
  /*Call the integration using the available rule inputs*/
  local!integration:
  rule!SpaceX_getAllLaunches(
    pagingInfo: ri!pagingInfo,
    searchText: ri!searchText,
    launch_year: ri!launch_year,
    launch_success: ri!launch_success
  ),

  /*Transform the integration result into a DataSubset*/
  a!dataSubset(
    startIndex: ri!pagingInfo.startIndex,
    batchSize: ri!pagingInfo.batchSize,
    sort: ri!pagingInfo.sort,
    
    /*Use the totalCount returned by the response*/
    totalCount: tointeger(tointeger(local!integration.result.headers.'Spacex-Api-Count'),
    
    /*Use the list of launches for the record list data*/
    data: local!integration.result.body,
    
    /*If any launches were returned, use the flight number as the identifier*/
    identifiers: if(
      tointeger(local!integration.result.headers.'Spacex-Api-Count') > 0,
      local!integration.result.body.flight_number,
      {}
    )
  )  
)
  1. At this point, we can click Test Rule to ensure that our expression rule is returning a DataSubset.
  2. Save the expression rule.

Configure the Record View Source

Now we've configured our Record List Source, we can create our Record View Source. First, we will create an integration, and then we will create an expression wrap it.

Create an Integration for the Record View Source

The second integration we build will populate the record views. This integration should return a single object that will map to the Data Type for your record type.

We will be using the launches/{{flight_number}} endpoint to return a single SpaceX launch.

  1. Within an application in Appian Designer, click New and select Integration.
  2. For Connected System, we will again select the r/SpaceX API connected system.
  3. Set the integration Name to SpaceX_getOneLaunch.
    • Optionally, add a description.
  4. Set the Save In folder to SpaceX Rules
  5. Select Create. The integration will pop-up in a new tab.
  6. Create a rule input called id of type Number (Integer).
  7. Set the test value for ri!id to 1.
  8. Edit the Relative Path as an expression to set it to "launches/"&ri!id. This will be appended to the Base URL of the connected system to form a URL of "https://api.spacexdata.com/v3/launches/1, given our test value of 1 for ri!id. /xbr-tutorial-url-success-getOne
  9. At this point, we can click the Test Request button to see if we're on the right track. Given our test value of 1 for ri!id, this should return a success message: /xbr-tutorial-connected-system
  10. Like with our previous integration, under the success message, click Convert JSON to Appian value to convert this response body to an Appian dictionary.
  11. Save the integration.

Create an Expression Rule for the Record View Source

Now that our second integration is configured to back our record view, we once again need to create an expression to wrap it. This expression will act as the glue between the integration and the record type. It will call the integration and transform it into an Appian dictionary.

  1. Create a new expression rule and give it the name SpaceX_source_getOneLaunch
  2. Set the Save In folder to SpaceX Rules
  3. Give it the same rule input that our integration has: a rule input called id of type Number (Integer).
  4. Configure the expression rule to to call our integration and return an Appian dictionary.
    1
    
      rule!SpaceX_GetOneLaunch(id: ri!id).result.body
    
  5. At this point, you can ensure your expression rule is hooked up to your integration properly by setting a test value of 1 for ri!id and clicking Test.
  6. Save the expression rule.

Now that we have all of our setup complete, let's create and configure our new record type.

Create the Record Type

We will take a step-wise approach to configuring the record type, starting with source configuration, then setting up filters, followed by the record list, and finally the record type's summary view.

To begin:

  1. In your test application, click on the New dropdown, and select Record Type.
  2. Enter SpaceX Launch in the Name field and SpaceX Launches in the Plural Name of the records type.
  3. Click Create. The record type will open in a new tab.

Configure the Record List Source

Three things are needed when configuring a record type to accept expressions: a data type, a list view source expression, and a record view source expression. To access these fields, click on the Source & Default Filters page. From the Source dropdown select Expression.

Once expression is selected you will see the fields to define the data source.

  1. In the Data Type field, select the SpaceX_Launch CDT created earlier.
  2. In the Record List Source picker, select SpaceX_source_getAllLaunches.
    • For the Paging Info dropdown, select pagingInfo if it was not automatically selected.
    • For the Search Text dropdown, select searchText if it was not automatically selected.

/xbr-tutorial-sources-tab-listonly

Now, we've mapped the record type Paging Info and Search Text to our Record List Source. These values will be passed through the selected expression rule, into the integration, and ultimately through the query parameters to the r/SpaceX API.

At this point, we have a fully functioning Record List that can page and search. You can view this in Tempo by clicking the View Record List shortcut by the Record Type name.

/xbr-tutorial-recordListPreviewOne

We can test paging by using the paging controls at the bottom of the record list grid, as well as by sorting on grid columns.

We can test searching by entering different values into the search bar and verifying that they return different lists. This API requires an exact match for the rocket_name parameter, so try Falcon Heavy and Falcon 9.

The initial value for Paging Info has a startIndex of 1. The batchSize and sort are determined by the configuration options on the Edit List tab.

Configure the Record View Source

  1. Navigate back to the Source tab.
  2. In the Record View Source picker, select SpaceX_source_getOneLaunch.
    • For the Record Identifier dropdown, select id if it was not automatically selected.
  3. Save the record type.

/xbr-tutorial-sources-tab

We will come back to the Record View Source soon. First, however, let's enhance our record list by adding a User Filter.

Create a User Filter

To add a User Filter:

  1. Navigate to the User Filters tab.
  2. Create the New User Filter link at the bottom of the grid.
  3. Set the Name and Label to Launch Year.
  4. Select launch_year in the Rule Input dropdown.
  5. Unselect Users can select multiple choices. This API only allows a single selection per dropdown.
  6. Copy this expression into the Choices expression editor:
    1
    2
    3
    4
    
      a!recordFilterChoices(
       choiceLabels: {2015,2016,2017,2018,2019,2020},
       choiceValues: {2015,2016,2017,2018,2019,2020}
      )
    
  7. Test your configuration using the Filter Preview /xbr-tutorial-user-filter-preview
  8. Once you're satisfied with your user filter, click OK.
  9. Save your record.

Once again, at this point we can navigate to Tempo to verify that your new filter is interacting with your record list as expected. Incremental testing is a major key to success for expression-backed records.

For more practice, configure a second User Filter for the launch_success parameter using the ri!launch_success rule input

Configure the List View

Now that our search and filter is created, lets populate our record list with more meaningful data.

  1. In the record type, on the List page, ensure that the Grid option is selected for the Style and click on Edit List. A new modal will appear
  2. In the Edit Record List Modal, add a new Empty grid message. Something like No launches exist with this criteria.
  3. Next, set Rows to Display Per Page to 5. This controls the batchSize that is passed into Paging Info input for your Record List Source.
  4. We are going to keep all columns but Details. In the Columns section of the configuration pane, click on the red X next to the Details column.
    1. Click on the Mission Name link. The grid configuration pane will show details about that column.
    2. Note the Sort Field. This controls the sortInfo that is passed into Paging Info input for your Record List Source.
    3. Set the Weight to 2.
    4. Click on link under Component to drill into the column.
    5. Click on Record Link under Links to drill futher into the column.
    6. Click on rp!id under Identifier to edit the record link identifier. Set it to flight_number.
  5. Click OK.
  6. Save your record type.

You should end up with a list view that looks like this:

/xbr-tutorial-final-record-list

Create the Summary View

We're almost there! The last step of this tutorial is to create the summary view.

A summary view for an expression-backed record is no different, structurally, from a summary view for any other type of record. What may be different, however, is how you acquire the data.

  1. In your test application, click on the New dropdown, and select Interface.
  2. Give the interface a name like SpaceX_LaunchSummaryView and choose a rule folder to save into.
    • Optionally add a description.
  3. Select Create. The interface will pop-up in a new tab.
  4. Click on Expression Mode.
  5. In the Rule Inputs section, create a new rule input. Name it launch and set the data type to SpaceX_Launch
  6. Copy the expression below and paste in the interface definition.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    
    a!boxLayout(
     label: "Flight #"&ri!launch.flight_number&" Launch Info",
     contents: {      
       a!sideBySideLayout(
         items: {
           a!sideBySideItem(
             item: a!textField(
               label: "Date",
               labelPosition: "ADJACENT",
               value: ri!launch.launch_date_utc,
               readOnly: true
             )
           ),
           a!sideBySideItem(
             item: a!textField(
               label: "Name",
               labelPosition: "ADJACENT",
               value: ri!launch.rocket.rocket_name,
               readOnly: true
             )
           ),
           a!sideBySideItem(
             item: a!richTextDisplayField(
               label: "Success",
               labelPosition: "ADJACENT",
               value: a!richTextIcon(
                 icon:
                 if(
                   ri!launch.launch_success,
                   "check-circle",
                   "times-circle"
                 ),
                 color:
                 if(
                   ri!launch.launch_success,
                   "POSITIVE",
                   "NEGATIVE"
                 )
               )
             )
           )
         }
       ),
       a!textField(
         label: "Details",
         labelPosition: "ADJACENT",
         value: ri!launch.details,
         showWhen: not(isnull(ri!launch.details)),
         readOnly: true
       )
     },
     iscollapsible: true
    )
    
  7. Save your interface.

The last steps are to get the record's title and summary view configured.

  1. Go to the SpaceX_Launch record type.
  2. Navigate to the Views tab.
  3. In the Record Title expression editor, use rf!mission_name to give each record the title of launch mission.
  4. In the Views grid, click on Summary to open the Edit View modal.
  5. In the Interface expression editor, call the interface in the expression editor and pass in rp!id. Your expression should look something like the example below.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    rule!SpaceX_LaunchSummaryView(
     launch:
     'type!{urn:com:appian:types:spacex}SpaceX_Launch'(
       flight_number: rf!flight_number,
       mission_name: rf!mission_name,
       launch_year: rf!launch_year,
       launch_date_utc: rf!launch_date_utc,
       rocket: rf!rocket,
       launch_success: rf!launch_success,
       details: rf!details
     )
    )
    
  6. Click OK and save the record.

Congratulations! Your record is complete. It should look something like:

/xbr-tutorial-summary-view

Considerations When Using the Record Picker Component

If you want to use a record picker with your expression-backed record, it should just work as expected. You should not need to change your record definition. But, in case something is not working as desired, here are a few notes on how the record picker works and how you can tweak your record design to optimize for a record picker.

  • When a user types text into the picker field, it is equivalent to a user typing text into the search bar of the record list. The difference is that every new letter in the picker is a new call to the web service, whereas in the record list, the user must hit enter before any calls are made. This means increased load on the web service.
  • Once a record is picked, the component makes one call to the web service for every picked item to get the information displayed in the label. This could be problematic because there is often overhead in web service calls. For that reason, only use the record picker when the number of items you expect users to pick at one time is low.
  • Filters applied in the component are processed in the same way that default filters and user filters are processed. This means that any new filters in the picker needed to be handled accordingly in your source expression and data retrieval rule.

If this picker does not meet your needs in some way, use a custom picker.

Open in Github

On This Page

FEEDBACK