Part 1: Manipulate Rich Web Data in Flow Without Code (Apex-Defined Types)

Watch Intro Video

In Summer ’19, Flow gains the ability to manipulate the kinds of complex data objects that are typically returned from calls to web services. Using Apex Actions and External Service Registrations, Flow was already able to work with web data, but it had to be in the form of simple ‘primitives’ like strings and numbers. The problem with that is that data from the web and enterprise data retrieved via integration solutions like Mulesoft rarely is composed of nothing but primitives. Consider these snapshots of web data:

This Product data structure includes three different URLs and three different SKU numbers corresponding to the different sizes of the Product. Traditionally, you’d have to manipulate these data structures in code (or carry out transforms in Mulesoft’s developer-oriented Application environment). Flow’s new functionality provides a new option that requires no code, expanding the range of people that can work with these rich objects.

To demonstrate this, we’re going to build a Flow that takes that complex Mulesoft product data and breaks it up into three separate Salesforce product records.

Setting Up: Creating Mulesoft Actions in Flow

For our particular example, we’ll start with a Mulesoft endpoint that produces this JSON:

 
{
  "identifier": "1295527d-d3c7-11e7-9c84-06bf056d193e",
  "identifiers": [
    {
      "SKU": "LN-2230"
    },
    {
      "SKU": "LN-2232"
    },
    {
      "SKU": "LN-2231"
    }
  ],
  "price": {
    "amount": {
      "currencyValue": "24.00",
      "name": "Amount",
      "currency": "USD"
    },
    "salesUnit": {
      "code": "EA",
      "name": "Each"
    }
  },
  "description": "Lion Mane costume hat for cats and dogs SMALL: Best fits slim cats and kittens. Neck circumference 22-26cm LARGE: Best fits most cats or small dogs. Neck circumference up to 35cm",
  "model": "Lion Mane Costume",
  "brand": "SmartPets",
  "pictures": [
    "https://s3-us-west-1.amazonaws.com/mulesoft/catmane-S.jpg",
    "https://s3-us-west-1.amazonaws.com/mulesoft/catmane-L.jpg",
    "https://s3-us-west-1.amazonaws.com/mulesoft/catmane-M.jpg"
  ]
}

This data is returned by a Mulesoft application that you create by following the Mulesoft Quick Start. However, you can use one that I set up already. To test your connectivity out, open a terminal program and run:

curl -X GET
http://congosample.us-e2.cloudhub.io/api/products/1295527d-d3c7-11e7-9c84-06bf056d193e

If things are running correctly, you should get back the JSON shown above.

However, we want to access this data inside of Salesforce and inside Flow in particular. The first thing we’re going to do shows how this is done before now. I’m going to create an Apex Class that calls this same URL.

This class defines an Invocable Action by making use of the @InvocableMethod annotation. It also uses the Requests & Results pattern that’s described here. You can get an introduction to Invocable Actions here.

If we go to Flow, we can now easily find that action by dragging the Action element onto the screen and searching for it by name (Note the new Summer ’19 simplified palette).

Getting The Data To Salesforce From The Web

The basic way to get data from the web into Salesforce is via an Apex class. Notice that this class parses the response JSON into an Apex object called a WebProduct:

global with sharing  class GetWebProductViaMulesoft {
 
    @InvocableMethod
    public static List<Results> GetWebProductViaMulesoft(List<Requests> requests)
       {
            Http http = new Http();
            HttpRequest request = new HttpRequest();
            String endpoint = requests[0].endpoint;
            String submittedId = requests[0].submittedId;
            System.debug('url is: ' + endpoint + submittedId);
            request.setEndpoint(endpoint + submittedId );
            request.setMethod('GET');
            HttpResponse response = http.send(request);
           
            Results curResult = new Results();
            String responseJSON = response.getBody();
           
            //this particular Mulesoft endpoint returns json that includes as a keyword 'currency',
            //which is a disallowed reserved word in apex. So we need to transform it to something else before we can parse it
            responseJSON = responseJSON.replace('currency"', 'currencyType"');
           
            WebProduct curProduct = WebProduct.parse(responseJSON);        
            curResult.WebProduct = curProduct;
           
            List<Results> resultsList = new List<Results>();
            resultsList.add(curResult);
            return resultsList;
       }
    
    global class Requests {
        @InvocableVariable
        global String submittedId;
        
        @InvocableVariable
        global String endpoint;       
    }
    
    global class Results {
        @InvocableVariable
        global WebProduct product;
    }

}

Where did WebProduct come from? We created it by converting the JSON into Apex. To use rich web data in flow, you take the initial json and create an Apex representation of it:

Taking the JSON response from above and pasting it into the excellent tool at JSON2Apex, we get the following Apex:

Our GetWebProductViaMulesoft Apex class can get a rich web object from Mulesoft, turn it into Apex objects and work with it in code. Since we want to go farther and work with it Flow, we need to do 2 pieces of post-processing:

  1. Add the @AuraEnabled annotation to each property that we want to be present in Flow.
  2. Move each of the inner classes, such as Identifiers and Amount, into their own files.

Once this is done, we end up with five individual small class files like this:

By doing this work once, you subsequently can create many different Flows that work with this incoming data.

We’re setup to work with this endpoint via Flow. We’ll do that in Part 2.