Nav

Salesforce Composite Connector

The Anypoint Connector for Salesforce Composite provides you a way to integrate with Salesforce Composite API Salesforce Composite API. The connector exposes convenient methods for preparing sub-requests, execute them in one batch and parse the results. Also it offers the posibillity of creating SObject Trees through an operation separate from the batch ones, called "createSobjectTree". It provides DataSense on both preparation of sub-requests and parsing response of their execution and on the creation of the SObject Trees.

Read through this User Guide to understand how to set up and configure a basic integration flow using the connector. Read through the Technical Reference to understand how the connector operations tie in with the Salesforce Composite API calls. You will also find demo applications here that illustrate how to use the connector operations.

Prerequisites

This document assumes you are familiar with Mule, Anypoint Connectors, and Anypoint Studio Essentials To increase your familiarity with Studio, consider completing one or more Anypoint Studio Tutorials. Further, this page assumes that you have a basic understanding of Mule flows and Mule Global Elements.

Requirements

To use the Salesforce Composite connector, you need:

Compatibility

Application/Service Version

Mule Runtime

3.5.0 and higher

Salesforce Rest API

36.0

Installing and Configuring

Installing

You can install a connector in Anypoint Studio using the instructions in To Import an Asset from Exchange.

Using the Connector in a New Project

To use the Salesforce Composite connector in a Mule application project:

  1. In Studio, select File > New > Mule Project.

    Create new project

  2. Enter a name for your new project and leave the remaining options with their default values.

    Create new project dialog box

  3. If you plan to use Git, select Create a default .gitignore file for the project with default .gitignore settings for Studio Projects, and then click Next.

  4. Click Finish to create the project.

Configuring the Global Element

To use the Salesforce Composite connector in your Mule application, you must configure a global Salesforce Composite element that can be used by all the Salesforce Composite connectors in the application (read more about global elements).

Connector Authentication

To access the data in a Salesforce Composite instance, the connector uses "OAuth 2.0 Username-Password" flow. For more on how to obtain an access token with this method from Salesforce see: OAuth 2.0 Username-Password. Below are the steps for configuring global element using it:

  1. Click the Global Elements tab at the base of the canvas.

  2. On the Global Mule Configuration Elements screen, click Create.

  3. In the Choose Global Type wizard, filter by "salesforce composite", expand Connector Configuration, and then select "Salesforce Composite: Configuration".

    Create global element

  4. Click Ok

  5. Enter the global element properties:

    Basic authentication configuration

    In the image above, the placeholder values refer to a configuration file placed in the src folder of your project (Learn how to configure properties). You can either hardcode your credentials into the global configuration properties, or reference a configuration file that contains these values. For simpler maintenance and better re-usability of your project, Mule recommends that you use a configuration file. Keeping these values in a separate file is useful if you need to deploy to different environments, such as production, development, and QA, where your access credentials differ. See Deploying to Multiple Environments for instructions on how to manage this.
    Field Description

    Name

    Enter a name for this connector to reference it later.

    Username

    Enter a Salesforce username.

    Password

    Enter the corresponding password.

    Consumer Key

    Enter the consumer key for your connected app from Salesforce.

    Consumer Secret

    Enter the consumer secret for your connected app from Salesforce.

    Security token

    Enter the Security Token for the username.

    Token endpoint

    Enter the URL to server providing the token. For more info see: Understanding OAuth Endpoints.

Using the Connector

You can use the Salesforce Composite connector as an outbound connector in your flow to push data into Salesforce system by taking advantage of composite resource which is part of Salesforce REST Api. To use it as an outbound connector, simply place the connector in your flow at any point after an inbound endpoint.

Use cases

The purpose of this connector is to let you take advantage of composite resource of Salesforce REST API. It comes to you with operations that have DataSense support in order to give you the best user experience in preparing sub-requests that are going to be executed in one batch and also for parsing the responses that come from Salesforce. You have one operation for each resource supported by composite for preparing the sub-request that Salesforce Composite API expects, named "Pre <name_of_resource>", with the purpose of giving an easy way to create that sub-request and one operation for each resource with the purpose of giving an easy way to parse the response of its correlated sub-request, named "Post <name_of_resource>". You also have an operation responsible to send a list of sub-request to Salesforce and return a list of responses.

Another operation that this connector has available is "createSobjectTree" which creates one or more sObject trees with root records of the specified type (Salesforce SObject Tree documentation).

Adding the Salesforce Composite Connector to a Flow

  1. Create a new Mule project in Anypoint Studio.

  2. Drag the Salesforce Composite connector onto the canvas, then select it to open the properties editor.

  3. Configure the connector’s parameters:

    Salesforce Composite operation config

    Field Description

    Display Name

    Enter a unique label for the connector in your application.

    Connector Configuration

    Select a global element from the drop-drown that you have created under [Configuring the Salesforce Composite Global Element] section.

    Operation

    Select an operation for the connector to perform.

  4. Click the blank space on the canvas and save your configurations.

Example Use Cases

Example Use Case 1

In this use case it is described how to use the connector for preparing four sub-requests, execute them in one batch and parse the responses. The sub-requests that we are going to execute are update an account, update a contact, retrieve the updated account and contact, respectively. The input data that we need in order to create sub-requests will be read from a file and the results of execution are going to be also logged into a file. So lets get to work.

Create a new Mule Project by clicking on File > New > Mule Project. In the new project dialog box, the only thing you are required to enter is the name of the project. Click on Finish.

New project dialog

Now lets create the flow. Navigate through the project’s structure and double-click on src/main/app/project-name.xml and follow the steps below:

  1. Go to palette and search for "File".

  2. Drag and drop the "File" element on canvas. This element is going to read the file where we put input data needed for creating sub-requests.

    File element

  3. Double click on file element and set its properties as below:

    1. "Path" to "src/main/resources/input"

    2. "Move to Directory" to "src/main/resources/processed"

      Input File Config

  4. Go to palette, search for "Splitter" and drag and drop it on canvas after "File". This element is used for splitting input data into items each being used as input for operations responsible of preparing sub-requests. We will provide input data in xml format so will use xpath3 as a split expression.

    Input splitter

  5. Double click on "Splitter" and set its properties as below:

    1. "Enable Correlation" select "ALWAYS".

    2. "Expression" to "#[xpath3('/items/item', payload, 'NODESET')]"

      Input splitter config

  6. Go to palette, search for "DOM to XML" and drag and drop it on flow after "Splitter". We need this element because the result of splitter is a DOM object and the next component operates on strings in xml format.

  7. Go to palette, search for "Choice" and drag and drop it on flow after "DOM to XML". This element will route the input data item to its correlating "Composite" element based on its operation.

    Input Choice

  8. Go to palette, search for "Logger" and drag it inside "Default" section of "Choice".

  9. Double click on logger and set its properties as below:

    1. "Message" to "Unable to route item based on operation."

      Choice default branch logger

  10. Go to palette, search for "Transform Message" and drag inside the choice four of them one below the other.

  11. Go to palette, search for "Salesforce Composite" and drag one after each "Transform Message" from previous step.

  12. Right click on first "Transform Message" and rename it to "Update Account Transformer"

  13. Right click on first "Salesforce Composite" and rename it to "Pre-Update Account"

  14. Right click on second "Transform Message" and rename it to "Update Contact Transformer"

  15. Right click on second "Salesforce Composite" and rename it to "Pre-Update Contact"

  16. Right click on third "Transform Message" and rename it to "Retrieve Account Transformer"

  17. Right click on third "Salesforce Composite" and rename it to "Pre-Retrieve Account"

  18. Right click on fourth "Transform Message" and rename it to "Retrieve Contact Transformer"

  19. Right click on fourth "Salesforce Composite" and rename it to "Pre-Retrieve Contact"

    Input Choice with Branches

  20. Double click on "Choice" and set its properties as below:

    Input Choice Config

  21. From the bottom of the canvas switch to "Global Elements" tab and click on "Create". You are going to create global configuration for "Salesforce Conposite".

  22. In the search bar write "Salesforce Composite" and double click on "Salesforce Composite: Configuration" under "Connector Configuration".

    Salesforce Composite Global Config Search

  23. Fill all the fields as explained under [Configuring the Salesforce Composite Global Element]

    Salesforce Composite Config

  24. Double click on "Pre-Update Account" and set its properties as below. This is going to create the sub-request in format expected by Salesforce for updating an account.

    1. Select from "Connector configuration" drop down "Salesforce_Composite__Configuration" or the name that you have set while configuring the global element.

    2. Select from "Operation" drop down "Pre update"

    3. Select from "Type" drop down "Account"

    4. "Sub Request Correlation Id" to "updateAccountSubRequest". This id is going to be used to correlate the response with its parser.

      Pre Update Account

  25. Double click on "Pre-Update Contact" and set its properties as below. This is going to create the sub-request in format expected by Salesforce for updating a contact.

    1. Select from "Connector configuration" drop down "Salesforce_Composite__Configuration" or the name that you have set while configuring the global element.

    2. Select from "Operation" drop down "Pre update"

    3. Select from "Type" drop down "Contact"

    4. "Sub Request Correlation Id" to "updateContactSubRequest". This id is going to be used to correlate the response with its parser.

      Pre Update Contact

  26. Double click on "Pre-Retrieve Account" and set its properties as below. This is going to create the sub-request in format expected by Salesforce for retrieving an account.

    1. Select from "Connector configuration" drop down "Salesforce_Composite__Configuration" or the name that you have set while configuring the global element.

    2. Select from "Operation" drop down "Pre retrieve"

    3. "Sub Request Correlation Id" to "retrieveAccountSubRequest". This id is going to be used to correlate the response with its parser.

      Pre Retrieve Account

  27. Double click on "Pre-Retrieve Contact" and set its properties as below. This is going to create the sub-request in format expected by Salesforce for retrieving a contact.

    1. Select from "Connector configuration" drop down "Salesforce_Composite__Configuration" or the name that you have set while configuring the global element.

    2. Select from "Operation" drop down "Pre retrieve"

    3. "Sub Request Correlation Id" to "retrieveContactSubRequest". This id is going to be used to correlate the response with its parser.

      Pre Retrieve Contact

  28. Double click on "Update Account Transformer" and set its properties as below. This is going to map input data to expected data by operation that is preparing account update sub-request.

    Pre Update Account Transformer

  29. Double click on "Update Contact Transformer" and set its properties as below. This is going to map input data to expected data by operation that is preparing contact update sub-request.

    Pre Update Contact Transformer

  30. Double click on "Retrieve Account Transformer" and set its properties as below. This is going to map input data to expected data by operation that is preparing account retrieve sub-request.

    Retrieve Account Transformer

  31. Double click on "Retrieve Contact Transformer" and set its properties as below. This is going to map input data to expected data by operation that is preparing contact retrieve sub-request.

    Retrieve Contact Transformer

  32. Go to palette, search for "Collection Aggregator" and drag and drop it after "Choice". This is aggregating all the formatted sub-requests in a collection.

  33. Go to palette, search for "VM" and drag and drop it after "Collection Aggregator". It is used to pass the collection of sub-requests to the next flow.

    Sub-requests preparation full flow

  34. Double click on "Collection Aggregator" and set its properties as below:

    Sub-requests collection aggregator config

  35. Double click on "VM" and set its properties as below:

    Sub-requests VM config

  36. Go to palette, search for "VM" and drag and drop it in a new flow. This is used to get the collection of sub-requests from the precious flow.

    Pre and Post flow

  37. Double click on previously created "VM" and set its properties as below:

    Post VM config

  38. Go to palette, search for "Salesforce Composite" and drag and drop it after "VM". It is used to send the collection of sub-requests to Salesforce server and retrieve the collection of results.

  39. Go to palette, search for "Collection splitter" and drag and drop it after "Salesforce Composite". It is used to split the collection of results in individual messages for each result.

    Post Collection Splitter

  40. Double click on "Salesforce Composite" and set its properties as below:

    Execute batch config

  41. Double click on "Collection Splitter" and set its properties as below:

    Post Collection Splitter Config

  42. Go to palette, search for "First Successful" and drag and drop it after "Collection Splitter". It is used to route the result message to each connector from inside it until the message is successfully processed by one of them.

  43. Go to palette, search for "Salesforce Composite" and drag and drop four of them inside "First Successful". Each connector is used to handle one result message.

  44. Double Click on first "Salesforce Composite" and set its properties as below. It is responsible for parsing result of account update. This is decided based on its "Sub Request Correlation Id".

    1. "Display Name" to "Post Update Account"

    2. Select from "Connector configuration" drop down "Salesforce_Composite__Configuration" or the name that you have set while configuring the global element.

    3. Select from "Operation" drop down "Post update"

    4. "Sub Request Correlation Id" to "updateAccountSubRequest". This id is the one that you have set on "Pre Update Account" element.

      Post Update Account Config

  45. Double Click on second "Salesforce Composite" and set its properties as below. It is responsible for parsing result of contact update. This is decided based on its "Sub Request Correlation Id".

    1. "Display Name" to "Post Update Contact"

    2. Select from "Connector configuration" drop down "Salesforce_Composite__Configuration" or the name that you have set while configuring the global element.

    3. Select from "Operation" drop down "Post update"

    4. "Sub Request Correlation Id" to "updateContactSubRequest". This id is the one that you have set on "Pre Update Contact" element.

      Post Update Contact Config

  46. Double Click on third "Salesforce Composite" and set its properties as below. It is responsible for parsing result of account retrieval. This is decided based on its "Sub Request Correlation Id".

    1. "Display Name" to "Post Retrieve Account"

    2. Select from "Connector configuration" drop down "Salesforce_Composite__Configuration" or the name that you have set while configuring the global element.

    3. Select from "Operation" drop down "Post retrieve"

    4. "Sub Request Correlation Id" to "retrieveAccountSubRequest". This id is the one that you have set on "Pre Retrieve Account" element.

      Post Retrieve Account Config

  47. Double Click on fourth "Salesforce Composite" and set its properties as below. It is responsible for parsing result of contact retrieval. This is decided based on its "Sub Request Correlation Id".

    1. "Display Name" to "Post Retrieve Contact"

    2. Select from "Connector configuration" drop down "Salesforce_Composite__Configuration" or the name that you have set while configuring the global element.

    3. Select from "Operation" drop down "Post retrieve"

    4. "Sub Request Correlation Id" to "retrieveContactSubRequest". This id is the one that you have set on "Pre Retrieve Contact" element.

      Post Retrieve Contact Config

  48. After "Post Retrieve Account" drag and drop a "Transform Message". It is responsible for mapping the result of account retrieval to what data you need, in our case we pass it further as it is.

  49. After "Post Retrieve Contact" drag and drop a "Transform Message". It is responsible for mapping the result of contact retrieval to what data you need, in our case we pass it further as it is.

    Full First Successful

  50. Right click on first "Transform Message" and rename it to "Post Retrieve Account Transformer"

  51. Right click on second "Transform Message" and rename it to "Post Retrieve Contact Transformer"

  52. Double click on "Post Retrieve Account Transformer" and set its properties as below:

    Post Retrieve Account Transformer

  53. Double click on "Post Retrieve Contact Transformer" and set its properties as below:

    Post Retrieve Contact Transformer

  54. Go to palette, search for "Collection Aggregator" and drag and drop it after "First Successful". It is collection all the result messages formatted based on the user’s need.

  55. Go to palette, search for "Transform Message" and drag and drop it after "Collection Aggregator". It is converting the collected list of results into json format.

  56. Go to palette, search for "File" and drag and drop it after "Transform Message". It is writing the result json to a file.

    Result parsing flow

  57. Double click on "Collection Aggregator" and set its properties as below:

    Post execution collection aggregator

  58. Double click on "Transform Message" and set its properties as below:

    Post Execution Transformer

  59. Double click on "File" and set its properties as below:

    Execution result dump file

  60. We are almost done. The flow is ready and the only thing still left is to prepare input file and run the flow.

  61. Copy the following test file called items.xml into /src/main/resources/input

    
                 
              
    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
    
    <?xml version='1.0' encoding='windows-1252'?>
    <items>
      <item>
        <operation>updateAccount</operation>
        <sObject>
          <id><!--Account id to be updated --></id>
          <Phone>123123</Phone>
        </sObject>
      </item>
      <item>
        <operation>updateContact</operation>
        <sObject>
          <id><!--Contact id to be updated --></id>
          <Title>NewTitle</Title>
        </sObject>
      </item>
      <item>
        <operation>retrieveAccount</operation>
        <id><!--Account id to be retrieved --></id>
        <fields>
          <field>Id</field>
          <field>Name</field>
          <field>Phone</field>
        </fields>
        <type>Account</type>
      </item>
      <item>
        <operation>retrieveContact</operation>
        <id><!--Contact id to be retrieved --></id>
        <fields>
          <field>Id</field>
          <field>Name</field>
          <field>Title</field>
        </fields>
        <type>Contact</type>
      </item>
    </items>
  62. Replace "<!--Account id to be updated -->" with an account’s id from your organization. This is the account that the application is going to update.

  63. Replace "<!--Contact id to be updated -->" with an contact’s id from your organization. This is the contact that the application is going to update.

  64. Replace "<!--Account id to be retrieved -->" with an account’s id from your organization. This is the account that the application is going to retrieve.

  65. Replace "<!--Contact id to be retrieved -->" with an contact’s id from your organization. This is the contact that the application is going to retrieve.

  66. Run the application.

  67. Wait for the application to execute. It should take around 10 seconds. You know that the processing was finished when you see this message in console: "Writing file to: <path_to_app>\project-name\src\main\resources\output\batch_output.json".

  68. Open /src/main/resources/batch_output.json and see the result of processing in json format.

Example Use Case 2

  1. Add the sfdc-composite namespace to the mule element as follows:

    
                 
              
    1
    
    xmlns:sfdc-composite="http://www.mulesoft.org/schema/mule/sfdc-composite"
  2. Add the location of the composite schema referred to by the "sfdc-composite" namespace:

    
                 
              
    1
    
    http://www.mulesoft.org/schema/mule/sfdc-composite http://www.mulesoft.org/schema/mule/sfdc-composite/current/mule-sfdc-composite.xsd
  3. Add the data-weave namespace as follows:

    
                 
              
    1
    
    xmlns:dw="http://www.mulesoft.org/schema/mule/ee/dw"
  4. Add location of data weave schema referred by "dw" namespace with the following value:

    
                 
              
    1
    
    http://www.mulesoft.org/schema/mule/ee/dw http://www.mulesoft.org/schema/mule/ee/dw/current/dw.xsd
  5. Add the context namespace as follows:

    
                 
              
    1
    
    xmlns:context="http://www.springframework.org/schema/context"
  6. Add location of contact schema referred by "context" namespace with the following value:

    
                 
              
    1
    
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-current.xsd
  7. Add the file namespace as follows:

    
                 
              
    1
    
    xmlns:file="http://www.mulesoft.org/schema/mule/file"
  8. Add location of file schema referred by "file" namespace with the following value:

    
                 
              
    1
    
    http://www.mulesoft.org/schema/mule/file http://www.mulesoft.org/schema/mule/file/current/mule-file.xsd
  9. Add the vm namespace as follows:

    
                 
              
    1
    
    xmlns:vm="http://www.mulesoft.org/schema/mule/vm"
  10. Add location of vm schema referred by "vm" namespace with the following value:

    
                 
              
    1
    
    http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd
  11. Add a context:property-placeholder element to your project, then configure its attributes as follows:

    
                 
              
    1
    
    <context:property-placeholder location="mule-app.properties"/>
  12. Add a sfdc-composite:config element to your project, then configure its attributes as follows:

    
                 
              
    1
    
    <sfdc-composite:config name="Salesforce_Composite__Configuration" username="${config.username}" password="${config.password}" consumerKey="${config.consumerKey}" consumerSecret="${config.consumerSecret}" securityToken="${config.securityToken}" tokenEndpoint="${config.tokenEndpoint}" doc:name="Salesforce Composite: Configuration"/>
  13. Add an empty flow element to your project as follows:

    
                 
              
    1
    2
    
    <flow name="project-nameFlow">
    </flow>
  14. Within the flow element add a "file:inbound-endpoint" element as follows:

    
                 
              
    1
    
    <file:inbound-endpoint path="src/main/resources/input" moveToDirectory="src/main/resources/processed" responseTimeout="10000" doc:name="File"/>
  15. Within the flow element add a "splitter" element after file as follows:

    
                 
              
    1
    
    <splitter enableCorrelation="ALWAYS" expression="#[xpath3('/items/item', payload, 'NODESET')]" doc:name="Splitter"/>
  16. Within the flow element add a "mulexml:dom-to-xml-transformer" element after splitter as follows:

    
                 
              
    1
    
    <mulexml:dom-to-xml-transformer doc:name="DOM to XML"/>
  17. Within the flow element add an empty "choice" element after dom-to-xml transformer as follows:

    
                 
              
    1
    2
    3
    4
    
    <choice doc:name="Choice">
        <otherwise>
        </otherwise>
    </choice>
  18. Within the otherwise tag of choice element add a "logger" as follows:

    
                 
              
    1
    
    <logger message="Unable to route item based on operation." level="INFO" doc:name="Logger"/>
  19. Within the choice element add an empty "when" as follows:

    
                 
              
    1
    2
    
    <when expression="#[xpath3('/item/operation') == 'updateAccount']">
    </when>
  20. Within the "when" tag add a "dw:transform-message" as follows:

    
                 
              
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    <dw:transform-message doc:name="Update Account Transformer">
        <dw:set-payload>
            <![CDATA[
            %dw 1.0
            %output application/java
            ---
            {
                Phone: payload.item.sObject.Phone,
                Id: payload.item.sObject.id
            }
            ]]>
        </dw:set-payload>
    </dw:transform-message>
  21. Within the "when" tag add a "sfdc-composite:pre-update" after "dw:transform-message" as follows:

    
                 
              
    1
    
    <sfdc-composite:pre-update config-ref="Salesforce_Composite__Configuration" subRequestCorrelationId="updateAccountSubRequest" type="Account" doc:name="Pre-Update Account"/>
  22. Within the choice element add another empty "when" as follows:

    
                 
              
    1
    2
    
    <when expression="#[xpath3('/item/operation') == 'updateContact']">
    </when>
  23. Within the "when" tag add a "dw:transform-message" as follows:

    
                 
              
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    <dw:transform-message doc:name="Update Contact Transformer">
        <dw:set-payload>
        <![CDATA[
        %dw 1.0
        %output application/java
        ---
        {
            Id: payload.item.sObject.id,
            Title: payload.item.sObject.Title
        }
        ]]>
        </dw:set-payload>
    </dw:transform-message>
  24. Within the "when" tag add a "sfdc-composite:pre-update" after "dw:transform-message" as follows:

    
                 
              
    1
    
    <sfdc-composite:pre-update config-ref="Salesforce_Composite__Configuration" subRequestCorrelationId="updateContactSubRequest" type="Contact" doc:name="Pre-Update Contact"/>
  25. Within the choice element add another empty "when" as follows:

    
                 
              
    1
    2
    
    <when expression="#[xpath3('/item/operation') == 'retrieveAccount']">
    </when>
  26. Within the "when" tag add a "dw:transform-message" as follows:

    
                 
              
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    <dw:transform-message doc:name="Retrieve Account Transformer">
        <dw:set-payload>
            <![CDATA[%dw 1.0
            %output application/java
            ---
            {
                Id: payload.item.id,
                Fields : payload.item.fields.*field filter ($ != null and $ != ''),
                Type: payload.item.type
            }
            ]]>
        </dw:set-payload>
    </dw:transform-message>
  27. Within the "when" tag add a "sfdc-composite:pre-retrieve" after "dw:transform-message" as follows:

    
                 
              
    1
    
    <sfdc-composite:pre-retrieve config-ref="Salesforce_Composite__Configuration" doc:name="Pre-Retrieve Account" subRequestCorrelationId="retrieveAccountSubRequest"/>
  28. Within the choice element add another empty "when" as follows:

    
                 
              
    1
    2
    
    <when expression="#[xpath3('/item/operation') == 'retrieveContact']">
    </when>
  29. Within the "when" tag add a "dw:transform-message" as follows:

    
                 
              
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    <dw:transform-message doc:name="Retrieve Contact Transformer">
        <dw:set-payload>
            <![CDATA[%dw 1.0
            %output application/java
            ---
            {
                Id: payload.item.id,
                Fields : payload.item.fields.*field filter ($ != null and $ != ''),
                Type: payload.item.type
            }
            ]]>
        </dw:set-payload>
    </dw:transform-message>
  30. Within the "when" tag add a "sfdc-composite:pre-retrieve" after "dw:transform-message" as follows:

    
                 
              
    1
    
    <sfdc-composite:pre-retrieve config-ref="Salesforce_Composite__Configuration" doc:name="Pre-Retrieve Contact" subRequestCorrelationId="retrieveContactSubRequest"/>
  31. Within the flow element add a "collection-aggregator" element after "choice" as follows:

    
                 
              
    1
    
    <collection-aggregator timeout="10000" failOnTimeout="true" doc:name="Collection Aggregator"/>
  32. Within the flow element add a "vm:outbound-endpoint" element after "collection-aggregator" as follows:

    
                 
              
    1
    
    <vm:outbound-endpoint exchange-pattern="one-way" path="/toBeExecuted" doc:name="VM"/>
  33. Add another empty flow element to your project as follows:

    
                 
              
    1
    2
    
    <flow name="project-nameFlow1">
    </flow>
  34. Within the flow element add a "vm:inbound-endpoint" element as follows:

    
                 
              
    1
    
    <vm:inbound-endpoint exchange-pattern="one-way" path="/toBeExecuted" doc:name="VM"/>
  35. Within the flow element add a "sfdc-composite:execute-composite-batch" element after "vm:inbound-endpoint" as follows:

    
                 
              
    1
    
    <sfdc-composite:execute-composite-batch config-ref="Salesforce_Composite__Configuration" doc:name="Execute Sub-Requests"/>
  36. Within the flow element add a "collection-splitter" element after "sfdc-composite:execute-composite-batch" as follows:

    
                 
              
    1
    
    <collection-splitter enableCorrelation="ALWAYS" doc:name="Collection Splitter"/>
  37. Within the flow element add an empty "first-successful" element after "collection-splitter" as follows:

    
                 
              
    1
    2
    
    <first-successful doc:name="First Successful">
    </first-successful>
  38. Within the "first-successful" element add a "sfdc-composite:post-update" element as follows:

    
                 
              
    1
    
    <sfdc-composite:post-update config-ref="Salesforce_Composite__Configuration" subRequestCorrelationId="updateAccountSubRequest" doc:name="Post Update Account"/>
  39. Within the "first-successful" element add a "sfdc-composite:post-update" element as follows:

    
                 
              
    1
    
    <sfdc-composite:post-update config-ref="Salesforce_Composite__Configuration" subRequestCorrelationId="updateContactSubRequest" doc:name="Post Update Contact"/>
  40. Within the "first-successful" element add an empty "processor-chain" element as follows:

    
                 
              
    1
    2
    
    <processor-chain>
    </processor-chain>
  41. Within the "processor-chain" element add a "sfdc-composite:post-retrieve" element as follows:

    
                 
              
    1
    
    <sfdc-composite:post-retrieve config-ref="Salesforce_Composite__Configuration" subRequestCorrelationId="retrieveAccountSubRequest" type="Account" doc:name="Salesforce Composite"/>
  42. Within the "processor-chain" element add a "dw:transform-message" element as follows:

    
                 
              
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    <dw:transform-message doc:name="Post Retrieve Account Transformer">
        <dw:set-payload>
        <![CDATA[
        %dw 1.0
        %output application/java
        ---
        payload
        ]]>
        </dw:set-payload>
    </dw:transform-message>
  43. Within the "first-successful" element add another empty "processor-chain" element as follows:

    
                 
              
    1
    2
    
    <processor-chain>
    </processor-chain>
  44. Within the "processor-chain" element add a "sfdc-composite:post-retrieve" element as follows:

    
                 
              
    1
    
    <sfdc-composite:post-retrieve config-ref="Salesforce_Composite__Configuration" subRequestCorrelationId="retrieveContactSubRequest" type="Contact" doc:name="Salesforce Composite"/>
  45. Within the "processor-chain" element add a "dw:transform-message" element as follows:

    
                 
              
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    <dw:transform-message doc:name="Post Retrieve Contact Transformer">
        <dw:set-payload>
        <![CDATA[
        %dw 1.0
        %output application/java
        ---
        payload
        ]]>
        </dw:set-payload>
    </dw:transform-message>
  46. Within the flow element add a "collection-aggregator" element after "first-successful" as follows:

    
                 
              
    1
    
    <collection-aggregator timeout="10000" failOnTimeout="true" doc:name="Collection Aggregator"/>
  47. Within the flow element add a "dw:transform-message" element after "collection-aggregator" as follows:

    
                 
              
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    <dw:transform-message doc:name="Transform Message">
        <dw:set-payload>
            <![CDATA[
            %dw 1.0
            %output application/json
            ---
            payload
            ]]>
        </dw:set-payload>
    </dw:transform-message>
  48. Within the flow element add a "file:outbound-endpoint" element after "dw:transform-message" as follows:

    
                 
              
    1
    
    <file:outbound-endpoint path="src/main/resources/output" outputPattern="batch_output.json" responseTimeout="10000" doc:name="File"/>
  49. In the end the xml file should look like this:

    
                 
              
    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
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    
    <?xml version="1.0" encoding="UTF-8"?>
    
    <mule xmlns:vm="http://www.mulesoft.org/schema/mule/vm"
            xmlns:context="http://www.springframework.org/schema/context"
            xmlns:file="http://www.mulesoft.org/schema/mule/file"
            xmlns:dw="http://www.mulesoft.org/schema/mule/ee/dw"
            xmlns:mulexml="http://www.mulesoft.org/schema/mule/xml"
            xmlns:sfdc-composite="http://www.mulesoft.org/schema/mule/sfdc-composite"
            xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking"
            xmlns="http://www.mulesoft.org/schema/mule/core"
            xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
            xmlns:spring="http://www.springframework.org/schema/beans"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-current.xsd
    http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
    http://www.mulesoft.org/schema/mule/file http://www.mulesoft.org/schema/mule/file/current/mule-file.xsd
    http://www.mulesoft.org/schema/mule/xml http://www.mulesoft.org/schema/mule/xml/current/mule-xml.xsd
    http://www.mulesoft.org/schema/mule/ee/dw http://www.mulesoft.org/schema/mule/ee/dw/current/dw.xsd
    http://www.mulesoft.org/schema/mule/sfdc-composite http://www.mulesoft.org/schema/mule/sfdc-composite/current/mule-sfdc-composite.xsd
    http://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-current.xsd
    http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd">
        <sfdc-composite:config name="Salesforce_Composite__Configuration" username="${config.username}" password="${config.password}" consumerKey="${config.consumerKey}" consumerSecret="${config.consumerSecret}" securityToken="${config.securityToken}" tokenEndpoint="${config.tokenEndpoint}" doc:name="Salesforce Composite: Configuration"/>
        <context:property-placeholder location="mule-app.properties"/>
        <flow name="project-nameFlow">
            <file:inbound-endpoint path="src/main/resources/input" moveToDirectory="src/main/resources/processed" responseTimeout="10000" doc:name="File"/>
            <splitter enableCorrelation="ALWAYS" expression="#[xpath3('/items/item', payload, 'NODESET')]" doc:name="Splitter"/>
            <mulexml:dom-to-xml-transformer doc:name="DOM to XML"/>
            <choice doc:name="Choice">
                <when expression="#[xpath3('/item/operation') == 'updateAccount']">
                    <dw:transform-message doc:name="Update Account Transformer">
                        <dw:set-payload><![CDATA[%dw 1.0
    %output application/java
    ---
    {
            Phone: payload.item.sObject.Phone,
            Id: payload.item.sObject.id
    }]]></dw:set-payload>
                    </dw:transform-message>
                    <sfdc-composite:pre-update config-ref="Salesforce_Composite__Configuration" subRequestCorrelationId="updateAccountSubRequest" type="Account" doc:name="Pre-Update Account"/>
                </when>
                <when expression="#[xpath3('/item/operation') == 'updateContact']">
                    <dw:transform-message doc:name="Update Contact Transformer">
                        <dw:set-payload><![CDATA[%dw 1.0
    %output application/java
    ---
    {
            Id: payload.item.sObject.id,
            Title: payload.item.sObject.Title
    }]]></dw:set-payload>
                    </dw:transform-message>
                    <sfdc-composite:pre-update config-ref="Salesforce_Composite__Configuration" subRequestCorrelationId="updateContactSubRequest" type="Contact" doc:name="Pre-Update Contact"/>
                </when>
                <when expression="#[xpath3('/item/operation') == 'retrieveAccount']">
                    <dw:transform-message doc:name="Retrieve Account Transformer">
                        <dw:set-payload><![CDATA[%dw 1.0
    %output application/java
    ---
    {
            Id: payload.item.id,
            Fields : payload.item.fields.*field filter ($ != null and $ != ''),
            Type: payload.item.type
    }]]></dw:set-payload>
                    </dw:transform-message>
                    <sfdc-composite:pre-retrieve config-ref="Salesforce_Composite__Configuration" doc:name="Pre-Retrieve Account" subRequestCorrelationId="retrieveAccountSubRequest"/>
                </when>
                <when expression="#[xpath3('/item/operation') == 'retrieveContact']">
                    <dw:transform-message doc:name="Retrieve Contact Transformer">
                        <dw:set-payload><![CDATA[%dw 1.0
    %output application/java
    ---
    {
            Id: payload.item.id,
            Fields : payload.item.fields.*field filter ($ != null and $ != ''),
            Type: payload.item.type
    }]]></dw:set-payload>
                    </dw:transform-message>
                    <sfdc-composite:pre-retrieve config-ref="Salesforce_Composite__Configuration" doc:name="Pre-Retrieve Contact" subRequestCorrelationId="retrieveContactSubRequest"/>
                </when>
                <otherwise>
                    <logger message="Unable to route item based on operation." level="INFO" doc:name="Logger"/>
                </otherwise>
            </choice>
            <collection-aggregator timeout="10000" failOnTimeout="true" doc:name="Collection Aggregator"/>
            <vm:outbound-endpoint exchange-pattern="one-way" path="/toBeExecuted" doc:name="VM"/>
        </flow>
        <flow name="project-nameFlow1">
            <vm:inbound-endpoint exchange-pattern="one-way" path="/toBeExecuted" doc:name="VM"/>
            <sfdc-composite:execute-composite-batch config-ref="Salesforce_Composite__Configuration" doc:name="Execute Sub-Requests"/>
            <collection-splitter enableCorrelation="ALWAYS" doc:name="Collection Splitter"/>
            <first-successful doc:name="First Successful">
                <sfdc-composite:post-update config-ref="Salesforce_Composite__Configuration" subRequestCorrelationId="updateAccountSubRequest" doc:name="Post Update Account"/>
                <sfdc-composite:post-update config-ref="Salesforce_Composite__Configuration" subRequestCorrelationId="updateContactSubRequest" doc:name="Post Update Contact"/>
                <processor-chain>
                    <sfdc-composite:post-retrieve config-ref="Salesforce_Composite__Configuration" subRequestCorrelationId="retrieveAccountSubRequest" type="Account" doc:name="Salesforce Composite"/>
                    <dw:transform-message doc:name="Post Retrieve Account Transformer">
                        <dw:set-payload><![CDATA[%dw 1.0
    %output application/java
    ---
    payload]]></dw:set-payload>
                    </dw:transform-message>
                </processor-chain>
                <processor-chain>
                    <sfdc-composite:post-retrieve config-ref="Salesforce_Composite__Configuration" subRequestCorrelationId="retrieveContactSubRequest" type="Contact" doc:name="Salesforce Composite"/>
                    <dw:transform-message doc:name="Post Retrieve Contact Transformer">
                        <dw:set-payload><![CDATA[%dw 1.0
    %output application/java
    ---
    payload]]></dw:set-payload>
                    </dw:transform-message>
                </processor-chain>
            </first-successful>
            <collection-aggregator timeout="10000" failOnTimeout="true" doc:name="Collection Aggregator"/>
            <dw:transform-message doc:name="Transform Message">
                <dw:set-payload><![CDATA[%dw 1.0
    %output application/json
    ---
    payload]]></dw:set-payload>
            </dw:transform-message>
            <file:outbound-endpoint path="src/main/resources/output" outputPattern="batch_output.json" responseTimeout="10000" doc:name="File"/>
        </flow>
    </mule>

Example Use Case 3

In this use case it is described how to use the connector for creating SObject Trees.

  1. First we need to add an HTTP endpoint and configure it.

  2. Then we need to add the Salesforce Composite connector to the flow after the HTTP endpoint.

  3. The next step would be to create a configuration for the connector as in the previous use cases (see steps 22 and 23 from Example Use Case 1).

  4. After creating the configuration, we need to validate the credentials through the "Test Connection…​" button.

  5. Now that we know the credentials are ok and we can connect to Salesforce, we will choose the Operation that we want to execute, in this case: "Create sobject tree".

  6. Two parameters should appear under the General section: "SObject Root Type" and "SObject Tree".

  7. The "SObject Root Type" parameter represents the Sobject type of the root of the trees that will be created. When a value is chosen (e.g. "Account"), DataSense will bring the input and output metadata based on the chosen root type. The metadata tree has a depth of 5 levels, since that is the current limitation from Salesforce.

  8. The "SObject Tree" parameter will take as input a reference to a Map containing the Sobject Trees to be created. For more details you can check this SObject Tree Input example from Salesforce.

  9. To create the Map containig the tree, a Transform Message component can be used, to map the information from any format to the format expected by the operation.

  10. The output of the operation will contain the Salesforce Id, and the referece Id of the objects create successfully along with a flag called "hasErrors" that gives the status of the whole request ("false" if the entire tree was created successfully and "true" if the creation of any of the objects has failed).

  11. An example flow could be the one below:

    
                 
              
    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
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    
    <?xml version="1.0" encoding="UTF-8"?>
    
    <mule xmlns:json="http://www.mulesoft.org/schema/mule/json" xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" xmlns:dw="http://www.mulesoft.org/schema/mule/ee/dw" xmlns:metadata="http://www.mulesoft.org/schema/mule/metadata" xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:sfdc-composite="http://www.mulesoft.org/schema/mule/sfdc-composite" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
            xmlns:spring="http://www.springframework.org/schema/beans"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
    http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
    http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
    http://www.mulesoft.org/schema/mule/sfdc-composite http://www.mulesoft.org/schema/mule/sfdc-composite/current/mule-sfdc-composite.xsd
    http://www.mulesoft.org/schema/mule/ee/dw http://www.mulesoft.org/schema/mule/ee/dw/current/dw.xsd
    http://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd
    http://www.mulesoft.org/schema/mule/json http://www.mulesoft.org/schema/mule/json/current/mule-json.xsd">
        <http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration"/>
        <sfdc-composite:config name="Salesforce_Composite__Configuration" username="${config.username}" password="${config.password}" consumerKey="${config.consumerKey}" consumerSecret="${config.consumerSecret}" securityToken="${config.securityToken}" tokenEndpoint="${config.tokenEndpoint}" doc:name="Salesforce Composite: Configuration"/>
        <flow name="salesforce-composite-create-sobject-trees">
            <http:listener config-ref="HTTP_Listener_Configuration" path="/create-trees" doc:name="HTTP"/>
            <dw:transform-message metadata:id="ca0b6bb9-ba1d-4f8a-9ffd-cba303bd8903" doc:name="Transform Message">
                <dw:set-payload><![CDATA[%dw 1.0
    %output application/java
    ---
    payload.sObjectTrees.records map ((record , indexOfRecord) -> {
            attributes: {
                    type: record.attributes.type,
                    referenceId: record.attributes.referenceId
            },
            Name: record.Name,
            Phone: record.Phone,
            Website: record.Website,
            NumberOfEmployees: record.NumberOfEmployees as :number,
            (
                    ChildAccounts: {
                    records: record.ChildAccounts.records map ((record01 , indexOfRecord01) -> {
                            attributes: {
                                    type: record01.attributes.type,
                                    referenceId: record01.attributes.referenceId
                            },
                            Name: record01.Name,
                            Phone: record01.Phone,
                            Website: record01.Website,
                            NumberOfEmployees: record01.NumberOfEmployees as :number
                    })
            }
            ) when (record.ChildAccounts != null),
            Contacts: {
                    records: record.Contacts.records map ((record01 , indexOfRecord01) -> {
                            attributes: {
                                    type: record01.attributes.type,
                                    referenceId: record01.attributes.referenceId
                            },
                            LastName: record01.LastName,
                            Email: record01.Email,
                            Title: record01.Title
                    })
            }
    })]]></dw:set-payload>
            </dw:transform-message>
            <logger message="The input data is: #[payload]" level="INFO" doc:name="Log the payload after it is transformed into a Map"/>
    
            <sfdc-composite:create-sobject-tree config-ref="Salesforce_Composite__Configuration" type="Account" doc:name="Composite Create SObject Tree"/>
            <logger message="The result is: #[payload]" level="INFO" doc:name="Log the result received from Salesforce"/>
            <dw:transform-message doc:name="Transform the response from Salesforce to JSON">
                <dw:set-payload><![CDATA[%dw 1.0
    %output application/json
    ---
    {
            "hasErrors" : payload.hasErrors,
            "results" : payload.results
    }]]></dw:set-payload>
            </dw:transform-message>
        </flow>
    </mule>
    
  12. DataWeave was used in the previous example to map the trees taken from a JSON to the Map that the operation is expecting.

  13. For a practical example you can check the "salesforce-composite-sobject-tree-demo" from Technical Reference.

See Also