article by Frank Nimphius, September 2019
This article uses the example of a pasta menu to explain how to use an Apache FreeMarker expression in a System.CommonResponse component to store selected data objects in a dialog flow variable. It's the Apache FreeMarker expression you should know about.
Problem Statement
You can use the System.CommonResponse component in Oracle Digital Assistant skills to assign values to dialog flow variables when users select a card or press an action item in a list. For this to work, the System.CommonResponse components uses postback actions that can send a JSON structure to the bot containing key-value pairs of variable names and the values to assign to the variables.
Explaining the Sample:
The pastas variable that is referenced from the variableIterator property holds an array of objects. Each object has the following attributes defined: name, description, image, carbs, price). The value of the object attributes are assigned to the variable names in the payload property.
So when the user clicks on a pasta in the rendered list of values, then the pasta name is displayed in the bot conversation to acknowledge the action. However, a JSON string with the variable names and values is sent to the bot for processing (updating the variables in the dialog flow). So in the image below, the following context variables were defined in the dialog flow: pastaName, pastaDescription, pastaImage, pastaCarbs. pastaPrice.
To print the user selected values, the displayChoice state accesses each variable to print their values. The image below shows the example at runtime
So what's the problem? Well, there is NO problem as everything works just fine. The only objection you may have for this approach is that you need to create dialog flow variables for each attribute in a data object, which can be quite a lot. What you would want is to use a single variable to save the selected data object (pasta) as a whole.
Solution: Assigning Multiple Attributes to a Variable
While you cannot use the System.CommonResponse component to directly copy an object to a variable, you can use Apache FreeMarker to model the object. The System.CommonResponse component below works with a single variable (of type string): selectedPasta.
Using Apache FreeMarker as shown in the screenshot below, the System.CommonResponse component creates attributes for the variable. The syntax for this is
variableName
attribute1: value1
attribute2: value2
…
The screenshot below thus creates a single object for all the data attributes. When a user clicks on the pasta list of values, then attributes and values will be assigned to one variable: selectedPasta
To print the content of the selectedPasta variable you use expression in the form of ${selectedPasta.value.attribute_name}
The use of a single variable to hold all the attributes is easier to work with, especially when you want to reset the variable in between using the System.ResetVariables component.
Is There Another Option?
Instead of saving the selected data objet to a variable, you could save the index the data object has in the array to a variable. This approach is explained in the following TechExchange article:
Discussing The Pro And Con Of Each Approach
The pro for saving the selected object in a variable is that any change to the array will not have an impact to the selected object as it is saved in a separate variable. The con for this solution is that changes to the data object structure (e.g. the pasta data object gets a new attribute "protein") requires a change to the System.CommonResponse component configuration.
The pro for saving the selected object index is that there is no change required to the System.CommonResponse component when the data structure of the pasta object changes. And even the display of the selected object can be created generic in that you use an ApacheFreeMarker expression that loops over the attribute names (keys) of the referenced data object. The con of this approach however is that a change to the array makes the index pointing to a wrong data object. Still the risk for this to happen can be considered low as you as the bot developer are in control over when the array changes (as you would have to call a custom component for this)
Related Content
TechExchange Quick-Tip: Accessing Attribute Names and Values of a Data Object
