Integrating with Cloud Connect
Before learning how to use a Mule Cloud Connector, consider for a moment the various implications of using transports versus cloud connectors.
Both process messages
Both communicate with a remote systems using a protocol
Both can be configured as part of a Mule flow
Transports send messages. Cloud connectors invoke SaaS API operations.
Transports implement a specific protocol. Cloud connectors use a protocol under the covers (you don’t need to know what is used or work with it.)
Transports are generic. Cloud connectors are service specific. (Service specific transport configuration is reused inside the cloud connector implementation.)
In summary Cloud Connectors provide a higher level of abstraction that simplifies the integration with SAAS applications and cloud infrastructure while promoting reuse.
You can mix and match cloud connectors and transports freely within your Mule flows.
|Mule Flow A [Mule Flow] is a very flexible way of building integration solutions that is both powerful and intuitive.|
The following samples show how Cloud Connectors can be used in Mule Flows to perform integration with cloud services. These examples use the Twitter cloud connector.
In this very first example we simply re-expose a cloud connector operation over a Mule transport of our choice. In the configuration snippet below we a http inbound endpoint is configured followed by a our Twitter "public-timeline" operation. When we [test this flow in MuleIDE], Mule will listen on localhost port 8080 for any requests. When one is received, the Twitter public timeline operation is invoked, and it responds with the results. In the case of Twitter, the results are formatted according to the Twitter connector configuration.
This example also uses the logger to output the result set. This optional element can be used for debugging.
1 <twitter:config name="twitter" format="XML"/><flow name="twitterPublicTimelineProxy"> <http:inbound-endpoint host="localhost" port="8080"/> <twitter:public-timeline/> <logger message="#[payload]" level="INFO"/></flow>
This example is very similar to the one above, but this time a parameter is provided and used in the invocation of the cloud service operation. To invoke the flow shown below you would use the following url http://localhost:8080/?query=mule.
1 2 3 4 5 6 <twitter:config name="twitter" format="JSON"/> <flow name="twitterSearchProxy"> <http:inbound-endpoint host="localhost" port="8080"/> <twitter:search query="#[header:INBOUND:query]"/> <logger message="#[payload]" level="INFO"/> </flow>
This example uses a query parameter to pass in the Twitter search term, but if a message was sent to the inbound http endpoint using POST, this value could easily be extracted from the message using another expression evaluator such as XPATH, as shown here:
1 2 3 4 <flow name="twitterSearchProxy"> <http:inbound-endpoint host="localhost" port="8080"/> <twitter:search query="#[xpath:/my/element/with/query]"/> </flow>
This is an example of how an incoming message is used to invoke a cloud service operation using expressions to extract values from the message.
You’ve now seen two examples where a cloud service operation is invoked as part of a synchronous flow that implements a proxy scenario in which where the result from the cloud service is returned to the client.
Cloud operations can also be used in asynchronous Mule flows, when the result doesn’t need to be returned over the same channel.
Next, consider two examples that show asynchronous flow, that is, where the message flow is one-way. The first example snippet uses a http endpoint which by default uses a request-response exchange pattern. In this case, however, the <async> element is used to invoke the cloud connect asynchronously.
1 2 3 4 5 6 <flow name="asyncUpdateTwitterStatus"> <http:inbound-endpoint host="localhost" port="8080"/> <async> <twitter:update-stats status="#[json:/node/with/status]"/> </async> </flow>
The second example shows the use of a JMS endpoint, JMS Transport to receive new statuses from a JMS queue. JMS endpoints are one-way by default, meaning therefore, you don’t need to use the <async> element
1 2 3 4 <flow name="asyncUpdateTwitterStatus"> <jms:inbound-endpoint queue="twitterStatusQueue/> <twitter:update-stats status="#[xpath:/element/with/status]"/> </flow>
Another way to interact with cloud services is to poll them. Polling can be invoke an outbound endpoint (or any message process) at a defined frequency with the result being used as a new message that invokes the flow. This example shows the use of <poll>:
1 2 3 4 5 6 <flow name="cloudPolling"> <poll frequency="60000"> <twitter:search query="mule"/> </poll> ... </flow>
The polling example above will produce Twitter search results for "mule" every 60 seconds. You may receive repeated results in each poll.
Because it’s part of Mule, we can quickly and easily make this polling into a stream of unique tweets by adding a few lines of XML.
Using splitter and an idempotent filter, this is quite straightforward. The splitter splits out the search results into individual tweets, and the idempotent filter removes any duplicate tweets using the tweet id as a unique id.
1 2 3 4 5 6 7 8 <flow name="cloudPolling"> <poll frequency="60000"> <twitter:search query="mule"/> </poll> <splitter evaluator="json" expression="results" /> <idempotent-message-filter idExpression="#[json:id]"/> <logger message="@#[json:from_user] - #[json:text]" level="INFO" /> </flow>
So far, the scenarios you’ve seen use either a cloud service as a source of messages for the flow or use a cloud service in the flow to perform some operation. What if you want to use a cloud service to add to an existing message based on some information that already exists? This is called enrichment, and again, the brevity of the XML should impress you:
1 2 3 4 5 6 7 8 <twitter:config name="twitter"/> <flow name="cloudEnrichment"> <http:inbound-endpoint host="localhost" port="8080"/> <enricher target="#[header:userLang] source="#[json:lang]> <twitter:user screenName="#[xpath:/element/with/screenName]"/> </enricher> <http:outbound-endpoint host=".." port=""/> </flow>
In this example the message is enriched by adding an a header called userLang to the message with the user language code as retrieved from Twitter.
Instead of enriching the message directly, you can set a variable in the Mule Flow that can be used later by the expression. In this case, the expression is on the
<when> choice element, and it’s used to route the message.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <twitter:config name="twitter"/> <flow name="cloudRouting"> <http:inbound-endpoint host="localhost" port="8080"/> <enricher target="#[variable:userLang] source="#[json:lang]> <twitter:user screenName="#[xpath:/element/with/screenName]"/> </enricher> <choice> <when evaluator="variable" expression="userLang=en"> .. </when> <when evaluator="variable" expression="userLang=es"> .. </when> <otherwise> .. </otherwise> </choice> </flow>
The Twitter cloud connect operation that looks up user information is used here to determine the user’s language and then route the source message based on this information.
The variable expression evaluator/enricher are used to store and retrieve flow-scoped variables.