Salesforce Contact Aggregation Example
This example application uses the Salesforce connector to query contacts from two separate Salesforce instances and determine which contacts are present in both instances. The section immediately below describes the functions of each of the flows in the application. The section further below describes the configuration of the Salesforce Global Connector Configuration through which the Mule application establishes a connection to Salesforce.
Beyond this example, access introductory and reference documentation for the Salesforce Connector.
Prerequisites
This document assumes that you are familiar with Mule, the Anypoint Studio interface, Global Elements, DataSense, and the DataWeave or its predecessor, Datamapper. Further, it is assumed that you are familiar with Salesforce and have a developerforce account. Learn more about flows and subflows to gain more insight into the design of this example.
Understanding the Flows
The sections immediately below describe the functions of each of the flows.
mainFlow
Invoked by the triggerFlow (configured in a separate mflow file in the application), the mainFlow begins processing the message triggerFlow accepted via HTTP request. The mainFlow consists of four Flow Ref scopes, which successively call the four subflows in the application. The flow also references a catch exception strategy to handle exceptions thrown. At runtime, the mainFlow begins by calling the gatherDataFlow, explained below the example.
<mule xmlns:file="http://www.mulesoft.org/schema/mule/file" xmlns:smtp="http://www.mulesoft.org/schema/mule/smtp"
xmlns:http="http://www.mulesoft.org/schema/mule/http"
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.mulesoft.org/schema/mule/smtp http://www.mulesoft.org/schema/mule/smtp/current/mule-smtp.xsd
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/file http://www.mulesoft.org/schema/mule/file/current/mule-file.xsd">
<!-- In this file you should declare all your inbound endpoints and from here control the access to your application -->
<flow name="triggerFlow" processingStrategy="synchronous" doc:name="triggerFlow" doc:description="This is the simplest entry point to start the execution of your Template.
Here you should:
* Define any inbound endpoints
* Handle any input parameter and transform it into the expected format by the mainFlow.
Here you should not:
* Run validations against external systems
* Choose a flow of your application based on input parameters">
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration"/>
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="${http.port}" path="generatereport" doc:name="Start Report Generation"/>
<flow name="mainFlow>
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="call mainFlow"/>
</flow>
...
</mule>
gatherDataFlow
This flow contains two message enricher scopes with a Salesforce connector in each. Each Salesforce connector connects to a Salesforce instance to retrieve all fields of type Contact. The message enricher for each connector stores this information in two flow variables, one for each Salesforce organization.
At a later stage, the application accesses these two flow variables to determine which contacts are present in both organizations.
Studio Visual Editor
XML Editor
<sub-flow name="gatherDataFlow" doc:name="gatherDataFlow">
<enricher source="#[payload]" target="#[flowVars['contactsFromOrgA']]" doc:name="Store result in FlowVar 'contactsFromOrgA'">
<sfdc:query config-ref="SalesforceA" query="dsql:SELECT Name, Email, Id FROM Contact" doc:name="query all contacts from SalesForce instance A"/>
</enricher>
<enricher source="#[payload]" target="#[flowVars['contactsFromOrgB']]" doc:name="Store result in FlowVar 'contactsFromOrgB'">
<sfdc:query config-ref="SalesforceB" query="dsql:SELECT Name, Email, Id FROM Contact" doc:name="query all contacts from SalesForce instance B"/>
</enricher>
</sub-flow>
As you can see, each Salesforce connector is inside an enricher scope. The first Salesforce connector queries "Salesforce instance A" for contact data; Mule uses the enricher scope to record this data as in a flow variable, contactsFromOrgA
. At this point, the application has all contacts from "Salesforce instance A" stored in this variable.
Then, the second Salesforce connector and the second enricher repeat the above-described exercise with "Salesforce instance B", storing contact data for the instance in the flow variable contactsFromOrgB
.
Each Salesforce connector references a Salesforce global element, which is configured with the connection parameters (user ID, password, etc.) for each Salesforce organization. To see the configuration for each global element, see the Salesforce Global Elements section.
The table below lists the configuration for the Salesforce connector ("instance A"). This configuration is identical to that of the second Salesforce connector ("instance B"), except that each connector references a different global element.
Studio Visual Editor
Properties Editor
Parameter | Value |
---|---|
Display Name |
|
Connector Configuration |
|
Operation |
|
Language |
|
Query Text |
|
Fetch Size |
|
XML Editor
<sfdc:query config-ref="SalesforceA" query="dsql:SELECT Name, Email, Id FROM Contact" doc:name="query all contacts from SalesForce instance A"/>
After the application has created the two variables containing the contact information for both Salesforce organizations, mainFlow calls the aggregationFlow subflow.
aggregationFlow
This subflow contains only one element: a Java component, which invokes custom-built activity. This component takes both lists of contacts – the one contained in flow variable contactsFromOrgA
and the one from contactsFromOrgB –
and merges them into a single list. The application passes the merged list back to the mainFlow, then onwards to the formatOutputFlow.
formatOutputFlow
In this flow, a custom Java component searches merged contact list produced by aggregationFlow for elements with identical content in the Email
field. Any that appear more than once signify contacts that exist in both Salesforce organizations. This Java component outputs these "duplicates" another list.
Next, a DataMapper transformer maps the Java object to a CSV file which the flow then transforms to a string. The flow passes the message, now a string of duplicated email addresses back to the mainFlow. The mainFlow proceeds to send the message to the outboundFlow (configured in a separate mflow file in the application) to email the results to a pre-defined address.
<mule xmlns:file="http://www.mulesoft.org/schema/mule/file" xmlns:smtp="http://www.mulesoft.org/schema/mule/smtp"
xmlns:http="http://www.mulesoft.org/schema/mule/http"
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.mulesoft.org/schema/mule/smtp http://www.mulesoft.org/schema/mule/smtp/current/mule-smtp.xsd
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/file http://www.mulesoft.org/schema/mule/file/current/mule-file.xsd">
<!-- In this file you should declare all your inbound endpoints, and from here control the access to your application. -->
...
<flow name="outboundFlow" doc:name="outboundFlow" doc:description="This is the simplest output point to push the result of the data processing.
Here you should:
* Call external systems through outbound endpoints
Here you should not:
* Perform generic data transformation
The outboundFlow is in this file in order to maintain the logical abstraction of the Template.">
<file:outbound-endpoint path="/Users/admin/_marcos/sfdc-templates/sfdc2sfdc-contact-aggregation-main/_output" outputPattern="result.txt" responseTimeout="10000" doc:name="Write output"/>
</flow>
</mule>
Salesforce Global Elements
The tables below list the configuration for the Salesforce global element which establishes a connection to "Salesforce instance A".
Studio Visual Editor
General Tab
Properties Editor
Parameter | Value |
---|---|
Name |
|
Username |
Redacted. Use the appropriate user ID for your Salesforce instance. |
Password |
Redacted. Use the appropriate password for your Salesforce instance. |
Security Token |
Redacted. Use the appropriate security token for your Salesforce instance. |
Url |
Redacted. Use the appropriate URL for your Salesforce instance, such as |
Proxy Host |
|
Proxy Port |
|
Proxy Username |
|
Proxy Password |
|
Session Id |
|
Service Endpoint |
|
Enable DataSense |
True |
Time Object Store Reference |
|
Assignment Rule Id |
|
Client Id |
|
Batch Sobject Max Depth |
|
Allow Field Truncation Support |
|
Use Default Rule |
Pooling Profile Tab
In this tab, all settings reflect their default values.
Properties Editor
Parameter | Value | |
---|---|---|
Max active |
|
Max idle |
|
Initialisation policy |
|
Exhausted action |
|
Max wait |
|
Min eviction (ms) |
|
Reconnection Tab
In this tab, all settings reflect their default values.
Properties Editor
Parameter | Value |
---|---|
Do not use a Reconnection strategy |
Checked |
Run the reconnection in a separated thread |
Unchecked |
See Also
-
Access the introductory material for the Salesforce Connector.
-
Access full reference documentation for the Salesforce Connector.
-
Learn more about flow variables.
-
Learn more about Flows and Subflows.
-
Learn more about Anypoint Connectors in general.