Contact Us 1-800-596-4880

Splitter Flow Control Reference

Mule Runtime Engine versions 3.5, 3.6, and 3.7 reached End of Life on or before January 25, 2020. For more information, contact your Customer Success Manager to determine how you can migrate to the latest Mule version.

The Splitter Flow Control splits a message into separate fragments, then sends these fragments one at a time to the next message processor in the flow. Segments are identified based on an expression parameter, usually written in Mule Expression Language (MEL), but other formats can be employed also. You can then use a Collection Aggregator Flow Control to reassemble the parts of the original message. You can also include a Resequencer Flow Control to put the parts back into the original sequence in case they are shuffled out of order.

Splitting and aggregating the message is especially useful when you intend to process the split parts in asynchronous flows running on separate servers. Together, the splitter and aggregator flow controls allow you to share the workload among several servers and still be able to reassemble the message after it’s processed.

Weigh the pros and cons of using a splitter and aggregator in your flow, versus using a "Foreach" scope here.

Splitter Configuration

Studio Visual Editor

Splitter
Field Description Default Value Example XML

Display Name

Customize to display a unique name for the splitter in your application.

Splitter

doc:name="Splitter"

Enable Correlation

Specifies whether Mule should give outgoing messages a correlation ID. Options are:

  • IF_NOT_SET(existing correlation IDs are maintained)

  • ALWAYS (existing correlation IDs are overridden)

  • NEVER (no action)

IF_NOT_SET

enableCorrelation="IF_NOT_SET"

Message Info Mapping

Optional. If this child element is not configured, MuleMessage.getCorrelationId() is used, which is optimal for most use cases. Maps attributes from incoming data to construct Correlation ID and Message ID on outgoing messages.

<expression-message-info-mapping messageIdExpression="#[java.util.UUID.randomUUID().toString()]" correlationIdExpression="#[xpath3('//order/@id')]"/>

Expression

Expression to define how to split the message. This is a required field.

expression="#[xpath3('//item')]"

XML Editor or Standalone

Simple Splitter

<splitter expression="#[xpath3('//item')]" doc:name="Splitter" enableCorrelation="IF_NOT_SET"/>
Element Description

splitter

Splits a message into separate fragments, then sends these fragments one at a time to the next message processor in the flow.

Attribute Description

doc:name

Customize to display a unique name for the splitter in your application.

Note: Attribute not required in Mule Standalone configuration.

expression

Expression to define how to split the message. This is a required field.

enableCorrelation

Specifies whether Mule should give outgoing messages a correlation ID. Options are:

  • `IF_NOT_SET `(Default. Existing correlation IDs are maintained)

  • `ALWAYS `(Existing correlation IDs are overridden)

  • `NEVER `(No action)

Advanced Splitter Including a Child Element

Note that this example includes the optional child element, expression-message-info-mapping. Use this child element only if your aggregation (later in your flow) is extremely customized and the standard correlation id set by Mule does not meet your needs.
<splitter expression="#[xpath3('//item')]" doc:name="Splitter" enableCorrelation="IF_NOT_SET">
   <expression-message-info-mapping messageIdExpression="#[java.util.UUID.randomUUID().toString()]" correlationIdExpression="#[xpath3('//order/@id')]"/>
</splitter>
Child Element Description

expression-message-info-mapping

Optional. If this child element is not configured, MuleMessage.getCorrelationId() is used, which is optimal for most use cases. Maps attributes from incoming data to construct Correlation ID and Message ID on outgoing messages, according to the expressions in the attributes listed below.

Attribute Description

messageIdExpression

An expression that sets a custom message ID for each of the split messages. Must result in unique message Ids.

correlationIdExpression

An expression that sets a custom correlation ID for the split messages.

Basic Splitter Example

In this simple example, Mule splits an XML payload it into several items.

Studio Visual Editor

  1. Create a new Anypoint Studio project and drag an HTTP connector onto an empty canvas.

  2. Create a new Connector Configuration element for it by clicking the green plus sign next to the Connector Configuration field. Set localhost as the host and leave the default value 8081 as the port.

  3. Drag a Splitter Flow Control into the flow, to receive messages from the HTTP connector.

  4. Configure the Splitter as shown. In the Expression parameter, provide the expression //*:actor/text(), wrapped inside a MEL expression. This XPath expression selects every XML element named 'actor'. The splitter makes each of these (together with its children) into a new message.

    splitter_example
    Parameter Value

    Display Name

    Splitter

    Enable Correlation

    IF_NOT_SET

    Expression

    #[xpath3('//*:actor/text()'

  5. Add a Logger after the Splitter and set its message to #[message.payload] so that it logs the entire payload of each message that it receives.

    splitter+flow
  6. Run the Mule project.

  7. Send the HTTP Listener an HTTP request that includes a body with an attached XML file. You can use a browser extension such as Postman (Google Chrome), or the curl command line utility.

  8. Send a Post request to http://localhost:8081/ attaching XML to the body of the message. Sample XML is provided below.

    <root xmlns:foo="http://www.foo.org/" xmlns:bar="http://www.bar.org">
        <actors>
            <actor id="1">Christian Bale</actor>
            <actor id="2">Liam Neeson</actor>
            <actor id="3">Will Ferrell</actor>
        </actors>
        <foo:singers>
            <foo:singer id="4">Dave Grohl</foo:singer>
            <foo:singer id="5">B.B. King</foo:singer>
            <foo:singer id="6">Weird Al</foo:singer>
        </foo:singers>
    </root>

How to send the XML file as an attachment with the curl utility:

Save the XML code provided above to a file on your local drive.

Open a terminal and run the following command: curl -X POST --data @<your file> http://localhost:8081

If everything worked well, you should see three messages logged into the console, one for every "actor" XML element.

XML Editor or Standalone

  1. Add an HTTP Listener into a new flow, and use the default values for its attributes.

    <http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
    Attribute Value

    config-ref

    HTTP_Listener_Configuration

    path

    /

    doc:name

    HTTP

  2. For this element to work, you must include a Connector Configuration. The attribute in the connector named config-ref references this connector configuration element.

    <http:listener-config name="HTTP_Listener_Configuration" host="localhost" port="8081" doc:name="HTTP Listener Configuration"/>
    Attribute Value

    name

    HTTP_Listener_Configuration

    host

    localhost

    port

    8081

    doc:name

    HTTP

  3. Add a Splitter below, to receive messages from the HTTP connector. In the Expression parameter provide the expression //*:actor/text() , wrapped inside a MEL expression. This XPath expression selects every XML element named 'actor'. The splitter makes each of these (together with its children) into a new message.

    <splitter expression="#[xpath3('//*:actor/text()')]" doc:name="Splitter" enableCorrelation="IF_NOT_SET"/>
    Attribute Value

    expression

    #[xpath3('//actor')]

    doc:name

    Splitter

    enableCorrelation

    IF_NOT_SET

  4. Include a logger after the splitter to log the entire payload of each message received.

    <logger message="#[message.payload]" level="INFO" doc:name="Logger"/>
    Attribute Value

    message

    #[message.payload]

    level

    INFO

    doc:name

    Logger

  5. The finished flow should look like this:

    <http:listener-config name="HTTP_Listener_Configuration" host="localhost" port="8081" doc:name="HTTP Listener Configuration"/>
      <flow name="SplitterExampleFlow1" doc:name="SplitterExampleFlow1">
         <http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
            <splitter expression="#[xpath3('//*:actor/text()')]" doc:name="Splitter" enableCorrelation="IF_NOT_SET"/>
         <logger message="#[message.payload]" level="INFO" doc:name="Logger"/>
      </flow>
  6. Run the Mule project.

  7. Send the HTTP connector an HTTP request that includes a body with an attached XML file. MuleSoft recommends using a browser extension such as Postman (Google Chrome).

  8. Send a Post request to http://localhost:8081/ attaching an XML to the body of the message. Sample XML is provided below.

    <root xmlns:foo="http://www.foo.org/" xmlns:bar="http://www.bar.org">
        <actors>
            <actor id="1">Christian Bale</actor>
            <actor id="2">Liam Neeson</actor>
            <actor id="3">Will Ferrell</actor>
        </actors>
        <foo:singers>
            <foo:singer id="4">Dave Grohl</foo:singer>
            <foo:singer id="5">B.B. King</foo:singer>
            <foo:singer id="6">Weird Al</foo:singer>
        </foo:singers>
    </root>

    If everything worked well, you should see three messages logged into the console, one for each "actor" XML element.

Full Example Code

<?xml version="1.0" encoding="UTF-8"?>

<mule 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.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:listener-config name="HTTP_Listener_Configuration" host="localhost" port="8081" doc:name="HTTP Listener Configuration"/>

    <flow name="SplitterExampleFlow1" doc:name="SplitterExampleFlow1">
        <http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
        <splitter expression="#[xpath3('//*:actor/text()')]" doc:name="Splitter"/>
        <logger message="#[message.payload]" level="INFO" doc:name="Logger"/>
    </flow>
</mule>

Aggregating the Payload

When the splitter splits a message, it adds three new outbound variables into each of the output fragments. These three variables are later used by the Aggregator to reassemble the message:

  • MULE_CORRELATION_GROUP_SIZE: number of fragments into which the original message was split

  • MULE_CORRELATION_SEQUENCE: position of a fragment within the group

  • MULE_CORRELATION_ID: single ID for entire group (all output fragments of the same original message share the same value)

    variables+diagramv2

    You can look at the values of these outbound variables by putting a break point after the splitter and running your flow with the Visual Debugger:

variables

Thanks to these variables, when an aggregator receives a single fragment, it knows what group to put it into and how large this group should be. Once all of the fragments have arrived, it passes on the complete group as a single message.

diagram+ag+2

Aggregator Configuration

Studio Visual Editor

collection_agg
Field Description Default Value Example XML

Display Name

Customize to display a unique name for the splitter in your application.

Collection Aggregator

doc:name="Collection Aggregator"

Timeout

Defines a timeout in milliseconds to wait for events to be aggregated. By default the aggregator throws an exception if it is waiting for a correlation group and a timeout occurs before it receives all group entities.

none

timeout="60000"

Fail On Timeout

If set, your app fails if the aggregator times out.

false

failOnTimeout="true"

Message Info Mapping

Optional. If this child element is not configured, MuleMessage.getCorrelationId() is used, which is optimal for most use cases. Defines where to obtain Correlation ID and Message ID in incoming messages.

<expression-message-info-mapping messageIdExpression="#[java.util.UUID.randomUUID().toString()]" correlationIdExpression="#[xpath3('//order/@id')]"/>

Store Prefix

Defines the prefix of the ObjectStore names

none

storePrefix="split_"

XML View

Simple Collection Aggregator

<collection-aggregator failOnTimeout="true" doc:name="Collection Aggregator" storePrefix="split_" timeout="60000"/>
Element Description

collection-aggregator

Reassembles a message from separate fragments. Once all fragments have arrived it sends the full message to the next message processor in the flow.

Attribute Description

doc:name

Customize to display a unique name for the splitter in your application.

Note: Attribute not required in Mule Standalone configuration.

Timeout

Defines a timeout in milliseconds to wait for events to be aggregated. By default the aggregator throws an exception if it is waiting for a correlation group and a timeout occurs before it receives all group entities.

Fail On Timeout

If set, your app fails if the aggregator times out.

Message Info Mapping

Optional. If this child element is not configured, MuleMessage.getCorrelationId() is used, which is optimal for most use cases. Defines where to obtain Correlation ID and Message ID in incoming messages.

Prefix

Defines the prefix of the ObjectStore names

Advanced Collection Aggregator Including a Child Element

Note that this example includes the optional child element, expression-message-info-mapping. Use this child element only if your aggregation (later in your flow) is extremely customized and the standard correlation ID set by Mule does not meet your needs.
<collection-aggregator failOnTimeout="true" doc:name="Collection Aggregator" storePrefix="split_" timeout="60000">
            <expression-message-info-mapping messageIdExpression="#[java.util.UUID.randomUUID().toString()]" correlationIdExpression="#[xpath3('//order/@id')]"/>
</collection-aggregator>
Child Element Description

expression-message-info-mapping

Optional. If this child element is not configured, MuleMessage.getCorrelationId() is used, which is optimal for most use cases. Maps attributes of the arriving messages to messageIdExpression and correlationIdExpression.

Attribute Description

messageIdExpression

An expression that maps attributes of the arriving messages to messageIdExpression. Must result in unique message IDs.

correlationIdExpression

An expression that maps attributes of the arriving messages to correlationIdExpression. Must result in unique message IDs.

Example Splitting and Aggregating with Asynchronous Flows

This example builds upon the basic example above. Follow the steps below to run message fragments in asynchronous flows and then aggregate them back into a single message.

Studio Visual Editor

  1. Drag a VM connector to the end of the flow.

    splitter+flow+2
  2. Drag a second VM connector outside the existing flow, below it. This creates a new flow.

  3. Drag the existing logger you had in the first flow to the new second flow, after the VM connector.

    splitter+flow+3
  4. Configure the two VM connectors. Change both their Queue Path to step2.

    vm4

    Once both VMs have the same Queue Path configured, they will be linked. Messages that arrive to the first VM will continue their path out of the second VM.
    What you have at this point appears to work identically to what you built in the first example. There is, however, one key difference: each fraction of the message will be processed simultaneously rather than in sequence. If you deploy your app to a cluster of servers this will have a big effect on performance.

  5. Add a Collection aggregator in the second flow, after the Logger.

  6. Add one more logger after the Collection aggregator, to see how the final message is output.

    splitter+flow+4
  7. Run the Mule project.

  8. Send the HTTP connector an HTTP request that includes a body with an attached XML file.

  9. Send a Post request to http://localhost:8081/ attaching XML to the body of the message. Sample XML is provided below.

    The easiest way to do this is sending posts via a browser extension such as Postman (for Google Chrome) or the curl command line utility.
<root xmlns:foo="http://www.foo.org/" xmlns:bar="http://www.bar.org">
    <actors>
        <actor id="1">Christian Bale</actor>
        <actor id="2">Liam Neeson</actor>
        <actor id="3">Will Ferrell</actor>
    </actors>
    <foo:singers>
        <foo:singer id="4">Dave Grohl</foo:singer>
        <foo:singer id="5">B.B. King</foo:singer>
        <foo:singer id="6">Weird Al</foo:singer>
    </foo:singers>
</root>

You should see four messages logged into the console: the first three should be short, one for every "actor" XML element (notice the ID attribute in each message). After these first three messages there should be a fourth, longer message, which is logged after the aggregator has run. Notice two things:

  • Although the aggregator was triggered three times, once for every fraction of the message that reached it, it produced one single output message, only when all of the fractions were in place

  • The aggregator assembles the message in the order in which fractions have arrived; the final message may be shuffled. If maintaining the original sequence is important to you, take a look at the Advanced Example 2 in this page

XML Editor

  1. Add a second flow to your project.

    <http:listener-config name="HTTP_Listener_Configuration" host="localhost" port="8081" doc:name="HTTP Listener Configuration"/>
    <flow name="splitterFlow1" doc:name="splitterFlow1">
         <http:listener config-ref="HTTP_Listener_Configuration" path="gettweets" doc:name="HTTP"/>
         <splitter expression="#[xpath3('//*:actor/text()')]" doc:name="Splitter"/>
         <logger level="INFO" doc:name="Logger" message="#[payload]"/>
    </flow>
    
    <flow name="splitterFlow2" doc:name="splitterFlow2">
    
    </flow>
    1. Remove the logger in the first flow, add an identical one inside the second flow.

      <http:listener-config name="HTTP_Listener_Configuration" host="localhost" port="8081" doc:name="HTTP Listener Configuration"/>
      <flow name="splitterFlow1" doc:name="splitterFlow1">
           <http:listener config-ref="HTTP_Listener_Configuration" path="gettweets" doc:name="HTTP"/>
           <splitter expression="#[xpath3('//*:actor/text()')]" doc:name="Splitter"/>
      
      </flow>
      
      <flow name="splitterFlow2" doc:name="splitterFlow2">
           <logger level="INFO" doc:name="Logger" message="#[payload]"/>
      </flow>
  2. Link both flows through a couple of VM connectors, an outbound connector in the first flow and an inbound connector in the second flow.

    <http:listener-config name="HTTP_Listener_Configuration" host="localhost" port="8081" doc:name="HTTP Listener Configuration"/>
    <flow name="splitterFlow1" doc:name="splitterFlow1">
         <http:listener config-ref="HTTP_Listener_Configuration" path="gettweets" doc:name="HTTP"/>
         <splitter expression="#[xpath3('//*:actor/text()')]" doc:name="Splitter"/>
    
         <vm:outbound-endpoint exchange-pattern="one-way" path="step2" doc:name="VM"/>
    </flow>
    
    <flow name="splitterFlow2" doc:name="splitterFlow2">
        <vm:inbound-endpoint exchange-pattern="one-way" path="step2" doc:name="VM"/>
    </flow>

    Provide these same attributes for both VM connectors:

    Attribute Value

    exchange-pattern

    one-way

    path

    step2

    doc:name

    VM

    Once both VMs share the same Queue Path, they are linked. Messages that arrive to the first VM continue their path out of the second VM. What you have at this point appears to work identically to what you built in the first example. There is, however, one key difference: each fraction of the message processes simultaneously rather than in sequence. If you deploy your app to a cluster of servers this has a big effect on performance.

  3. Add a Collection aggregator in the second flow, after the logger.

    <collection-aggregator failOnTimeout="false" doc:name="Collection Aggregator"/>
    Attribute Value

    failOnTimeout

    false

    doc:name

    Collection Aggregator

  4. Run the Mule project.

  5. Send the HTTP connector an HTTP request that includes a body with an attached XML file.

  6. Send a Post request to http://localhost:8081/ attaching XML to the body of the message. Sample XML is provided below.

    The easiest way to do this is sending posts via a browser extension such as Postman (for Google Chrome), or using the curl command-line utility.
<root xmlns:foo="http://www.foo.org/" xmlns:bar="http://www.bar.org">
    <actors>
        <actor id="1">Christian Bale</actor>
        <actor id="2">Liam Neeson</actor>
        <actor id="3">Will Ferrell</actor>
    </actors>
    <foo:singers>
        <foo:singer id="4">Dave Grohl</foo:singer>
        <foo:singer id="5">B.B. King</foo:singer>
        <foo:singer id="6">Weird Al</foo:singer>
    </foo:singers>
</root>

You should see four messages logged into the console: the first three should be short, one for every "actor" XML element (notice the ID attribute in each message). After these first three messages there should be a fourth, longer message, which is logged after the aggregator has run. Notice two things:

  • Although the aggregator was triggered three times, once for every fraction of the message that reached it, it produced one single output message, only when all of the fractions were in place

  • The aggregator assembles the message in the order in which fractions have arrived; the final message may be shuffled. If maintaining the original sequence is important to you, take a look at the Advanced Example 2 in this page

Full Example Code

<?xml version="1.0" encoding="UTF-8"?>

<mule xmlns:vm="http://www.mulesoft.org/schema/mule/vm" xmlns:scripting="http://www.mulesoft.org/schema/mule/scripting" xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" 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.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/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd
http://www.mulesoft.org/schema/mule/scripting http://www.mulesoft.org/schema/mule/scripting/current/mule-scripting.xsd
http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd">
    <http:listener-config name="HTTP_Listener_Configuration" host="localhost" port="8081" doc:name="HTTP Listener Configuration"/>
    <flow name="splitterFlow1" doc:name="splitterFlow1">
        <http:listener config-ref="HTTP_Listener_Configuration" path="gettweets" doc:name="HTTP"/>
        <splitter expression="#[xpath3('//*:actor/text()')]" doc:name="Splitter"/>
        <vm:outbound-endpoint exchange-pattern="one-way" path="step2" doc:name="VM"/>
    </flow>
    <flow name="splitterFlow2" doc:name="splitterFlow2">
        <vm:inbound-endpoint exchange-pattern="one-way" path="step2" doc:name="VM"/>
        <logger level="INFO" doc:name="Logger" message="#[payload]"/>
        <collection-aggregator failOnTimeout="true" doc:name="Collection Aggregator"/>
    </flow>
</mule>

Example Reordering Before Aggregating

This example builds upon the previous example.

If fractions of the message are being processed in parallel in different servers, there’s a good chance that they may take different lengths of time to be processed, and consequently fall out of order. The following example solves that problem.

Follow the steps below to:

  • Run message fragments in asynchronous flows

  • Arrange them back into the original sequence

  • Aggregate them back into a single message that follows the original sequence

Studio Visual Editor

  1. Add a Resequencer Flow Control before the aggregator

    splitter+flow+5

    The Resequencer waits for all of the messages in the group to arrive (keeping track of MULE_CORRELATION_ID and MULE_CORRELATION_GROUP_SIZE) and then reorders them according to their MULE_CORRELATION_SEQUENCE index.

    The Resequencer outputs three distinct messages, so the Aggregator is still needed to merge them into one.

  2. Run the Mule project.

  3. Send the HTTP connector an HTTP request that includes a body with an attached XML file.

  4. Send a Post request to http://localhost:8081/ attaching XML to the body of the message. Sample XML is provided below.

    The easiest way to do this is sending posts via a browser extension such as Postman (for Google Chrome), or the curl command-line utility.
    <root xmlns:foo="http://www.foo.org/" xmlns:bar="http://www.bar.org">
        <actors>
            <actor id="1">Christian Bale</actor>
            <actor id="2">Liam Neeson</actor>
            <actor id="3">Will Ferrell</actor>
        </actors>
        <foo:singers>
            <foo:singer id="4">Dave Grohl</foo:singer>
            <foo:singer id="5">B.B. King</foo:singer>
            <foo:singer id="6">Weird Al</foo:singer>
        </foo:singers>
    </root>

With the Resequencer in place, messages now reach the aggregator in the correct order and are assembled accordingly.

Try this demonstration:

To really take advantage of splitting the message, you should deploy your app to a cluster of servers. By following the steps below, you can simulate the random delays of a cluster of servers.

The following is not an implementable solution but rather a proof of concept that highlights what occurs in the flow.
  1. Add a Groovy component in the second flow, between the VM and the logger.

    splitter+flow+6
  2. Copy the following code into the Groovy Component:

    random = new Random()
    randomInt = random.nextInt(10)*1000
    Thread.sleep(randomInt)
    return payload

    This snippet of code simply introduces a random delay of up to 10 seconds. As each message is running asynchronously, this delay can potentially alter the order in which messages move on to the next step, simulating what could happen in a real implementation with parallel servers processing each fraction of the message.

  3. Run the project.

  4. Send the HTTP connector an HTTP request that includes a body with an attached XML file.

  5. Send a Post request to http://localhost:8081/ attaching XML to the body of the message. Sample XML is provided below.

    The easiest way to do this is sending posts via a browser extension such as Postman (for Google Chrome), or the curl command-line utility.
    <root xmlns:foo="http://www.foo.org/" xmlns:bar="http://www.bar.org">
        <actors>
            <actor id="1">Christian Bale</actor>
            <actor id="2">Liam Neeson</actor>
            <actor id="3">Will Ferrell</actor>
        </actors>
        <foo:singers>
            <foo:singer id="4">Dave Grohl</foo:singer>
            <foo:singer id="5">B.B. King</foo:singer>
            <foo:singer id="6">Weird Al</foo:singer>
        </foo:singers>
    </root>

You should now see three messages logged into the console, one for every "actor" XML element. These will likely not have their MULE_CORRELATION_SEQUENCE indexes in order due to the random delays caused by the Groovy code.

Below these, you will see a fourth longer message where these indexes are put back in order by the Resequencer.

XML Editor

  1. Add a Resequencer Flow Control before the aggregator.

    <resequencer failOnTimeout="true" doc:name="Resequencer"/>
    Attribute Value

    failOnTimeout

    true

    doc:name

    Resequencer

    The Resequencer waits for all of the messages in the group to arrive (keeping track of MULE_CORRELATION_ID and MULE_CORRELATION_GROUP_SIZE) and then reorders them according to their MULE_CORRELATION_SEQUENCE index.
    The Resequencer outputs three distinct messages, so the Aggregator is still needed to merge them into one.

  2. Run the Mule project.

  3. Send the HTTP connector an HTTP request that includes a body with an attached XML file.

  4. Send a Post request to http://localhost:8081/ attaching XML to the body of the message. Sample XML is provided below.

    The easiest way to do this is sending posts via a browser extension such as Postman (for Google Chrome) or the curl command-line utility.
    <root xmlns:foo="http://www.foo.org/" xmlns:bar="http://www.bar.org">
        <actors>
            <actor id="1">Christian Bale</actor>
            <actor id="2">Liam Neeson</actor>
            <actor id="3">Will Ferrell</actor>
        </actors>
        <foo:singers>
            <foo:singer id="4">Dave Grohl</foo:singer>
            <foo:singer id="5">B.B. King</foo:singer>
            <foo:singer id="6">Weird Al</foo:singer>
        </foo:singers>
    </root>

With the Resequencer in place, messages now reach the aggregator in the correct order and are assembled accordingly.

Try this demonstration:

To really take advantage of splitting the message, you should deploy your app to a cluster of servers. By following the steps below, you can simulate the random delays of a cluster of servers.

The following is not an implementable solution but rather a proof of concept that highlights what occurs in the flow.
  1. Add a Groovy component in the second flow, between the VM and the first logger.

    <scripting:component doc:name="Groovy">
        <scripting:script engine="Groovy">
            <![CDATA[
                random = new Random()
                randomInt = random.nextInt(10)*1000
                Thread.sleep(randomInt)
                return payload
            ]]>
        </scripting:script>
    </scripting:component>

    This snippet of code simply introduces a random delay of up to 10 seconds. As each message is running asynchronously, this delay can potentially alter the order in which messages move on to the next step, simulating what could happen in a real implementation with parallel servers processing each fraction of the message.

  2. Run the project.

  3. Send the HTTP connector an HTTP request that includes a body with an attached XML file.

  4. Send a Post request to http://localhost:8081/ attaching XML to the body of the message. Sample XML is provided below.

    The easiest way to do this is sending posts via a browser extension such as Postman (for Google Chrome) or the curl command-line utility.
<root xmlns:foo="http://www.foo.org/" xmlns:bar="http://www.bar.org">
    <actors>
        <actor id="1">Christian Bale</actor>
        <actor id="2">Liam Neeson</actor>
        <actor id="3">Will Ferrell</actor>
    </actors>
    <foo:singers>
        <foo:singer id="4">Dave Grohl</foo:singer>
        <foo:singer id="5">B.B. King</foo:singer>
        <foo:singer id="6">Weird Al</foo:singer>
    </foo:singers>
</root>

You should now see three messages logged into the console, one for every "actor" XML element. These will likely not have their MULE_CORRELATION_SEQUENCE indexes in order due to the random delays caused by the Groovy code.

Below these, you should see a fourth longer message where these indexes are in order by the Resequencer.

Full Example Code

<?xml version="1.0" encoding="UTF-8"?>

<mule xmlns:vm="http://www.mulesoft.org/schema/mule/vm" xmlns:scripting="http://www.mulesoft.org/schema/mule/scripting" xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" 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.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/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd
http://www.mulesoft.org/schema/mule/scripting http://www.mulesoft.org/schema/mule/scripting/current/mule-scripting.xsd
http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd">
    <http:listener-config name="HTTP_Listener_Configuration" host="localhost" port="8081" doc:name="HTTP Listener Configuration"/>

    <flow name="splitterFlow1" doc:name="splitterFlow1">
        <http:listener config-ref="HTTP_Listener_Configuration" path="gettweets" doc:name="HTTP"/>
        <splitter expression="#[xpath3('//*:actor/text()')]" doc:name="Splitter"/>
        <vm:outbound-endpoint exchange-pattern="one-way" path="step2" doc:name="VM"/>
    </flow>
    <flow name="splitterFlow2" doc:name="splitterFlow2">
        <vm:inbound-endpoint exchange-pattern="one-way" path="step2" doc:name="VM"/>
        <logger level="INFO" doc:name="Logger" message="#[payload]"/>
        <resequencer failOnTimeout="true" doc:name="Resequencer"/>
        <logger message="#[payload]" level="INFO" doc:name="Logger"/>
        <collection-aggregator failOnTimeout="true" doc:name="Collection Aggregator"/>
        <logger message="#[payload]" level="INFO" doc:name="Logger"/>
    </flow>
</mule>

See Also