Mule sub-flow example

0

When we want to reuse a portion of the flow, we extract the common sequence of message processors into a new sub flow using the <sub-flow> element.
A flow always starts with a message source whereas the subflow doesn’t need any message source is instead called from the main flow using <flow-ref>.

sub-flow characteristics

  1. sub-flow doesn’t have a message source as it is just a sequence of message processors put together and given a name
  2. sub-flow has to be explicitly invoked from some other flow
  3. When a sub-flow is called, it behaves as if the message processors in the subflow were in the main flow so the message properties of the sub-flow and main flow are same.

muleContext.xml:

<?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:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:vm="http://www.mulesoft.org/schema/mule/vm"
	xmlns:spring="http://www.springframework.org/schema/beans"
	xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd 
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd      
       http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/3.8/mule-vm.xsd
       http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/3.8/mule.xsd 
       ">
	<flow name="flow">
		<vm:inbound-endpoint path="subflow.test"
			exchange-pattern="request-response" />
		<flow-ref name="sub-flow" />
		<custom-transformer class="com.javarticles.mule.PrintOutboundProperty">
			<spring:property name="property" value="outbound_property" />
		</custom-transformer>
		<flow-ref name="sub-flow" />
	</flow>
	<sub-flow name="sub-flow">
		<custom-transformer class="com.javarticles.mule.PrintInboundProperty">
			<spring:property name="property" value="inbound_property" />
		</custom-transformer>
		<custom-processor class="com.javarticles.mule.StringAppender">
			<spring:property name="suffix" value="-" />
		</custom-processor>
		<append-string-transformer message="123" />
		<message-properties-transformer scope="outbound">
			<add-message-property key="outbound_property"
				value="NEW" />
		</message-properties-transformer>
	</sub-flow>

</mule>

Below message processor prints a specific inbound property.

PrintInboundProperty:

package com.javarticles.mule;

import org.mule.api.MuleMessage;
import org.mule.transformer.AbstractMessageTransformer;

public class PrintInboundProperty extends AbstractMessageTransformer {
    private String property;

    @Override
    public Object transformMessage(MuleMessage message, String encoding) {
        Object inboundProperty = message.getInboundProperty(property);
        System.out.println(Thread.currentThread().getName() + ":" + getProperty() + ": "+ inboundProperty);
        return message;
    }

    public String getProperty() {
        return property;
    }

    public void setProperty(String property) {
        this.property = property;
    }
}

Below message processor prints a specific outbound property.

PrintOutboundProperty:

package com.javarticles.mule;

import org.mule.api.MuleMessage;
import org.mule.transformer.AbstractMessageTransformer;

public class PrintOutboundProperty extends AbstractMessageTransformer {
    private String property;

    @Override
    public Object transformMessage(MuleMessage message, String encoding) {
        Object outboundProperty = message.getOutboundProperty(property);
        System.out.println(getProperty() + ": "+ outboundProperty);
        return message;
    }

    public String getProperty() {
        return property;
    }

    public void setProperty(String property) {
        this.property = property;
    }
}

A simple processor that transforms the message, appends a string to the existing payload.

StringAppender:

package com.javarticles.mule;

import org.mule.api.MuleEvent;
import org.mule.api.MuleException;
import org.mule.api.processor.MessageProcessor;

public class StringAppender implements MessageProcessor {
    private String suffix;

    public MuleEvent process(MuleEvent event) throws MuleException {
        event.getMessage().setPayload(event.getMessage().getPayload() + suffix);
        return event;
    }

    public void setSuffix(String suffix) {
        this.suffix = suffix;
    }
}

Send a message to the main flow, inbound point vm://subflow.test and then print its response.

MuleSubFlowExample:

package com.javarticles.mule;

import org.mule.DefaultMuleMessage;
import org.mule.api.MuleContext;
import org.mule.api.MuleMessage;
import org.mule.api.context.MuleContextBuilder;
import org.mule.api.context.MuleContextFactory;
import org.mule.config.DefaultMuleConfiguration;
import org.mule.config.spring.SpringXmlConfigurationBuilder;
import org.mule.context.DefaultMuleContextBuilder;
import org.mule.context.DefaultMuleContextFactory;
import org.mule.module.client.MuleClient;

public class MuleSubFlowExample {
    public static void main(String[] args) throws Exception {
        DefaultMuleConfiguration dmc = new DefaultMuleConfiguration();
        dmc.setId("muleexample");
        dmc.setWorkingDirectory("/esb/mule");
        SpringXmlConfigurationBuilder configBuilder = new SpringXmlConfigurationBuilder(
                "muleContext.xml");
        MuleContextBuilder contextBuilder = new DefaultMuleContextBuilder();
        contextBuilder.setMuleConfiguration(dmc);
        MuleContextFactory contextFactory = new DefaultMuleContextFactory();
        MuleContext ctx = contextFactory.createMuleContext(configBuilder,
                contextBuilder);
        ctx.start();
        try {
            MuleClient muleClient = new MuleClient(ctx);
            MuleMessage payload = createOutboundMessage(ctx);
            System.out.println("Sending payload [" + payload.getPayloadAsString()
                    + "] to vm://subflow.test");
            MuleMessage message = muleClient.send("vm://subflow.test", payload);
            System.out.println("Response: " + message.getPayload());
        } finally {
            ctx.dispose();
        }
    }

    private static MuleMessage createOutboundMessage(MuleContext ctx) {
        MuleMessage msg = new DefaultMuleMessage("XYZ", ctx);
        msg.setOutboundProperty("inbound_property", "ABC");
        return msg;
    }
}

We use the PrintInboundProperty processor to print the thread name and the inbound property.
As you can see from the output below, the inbound properties of the main flow and the sub-flow are same and is invoked in the same thread.

Output:

Sending payload [XYZ] to vm://subflow.test
main:inbound_property: ABC
outbound_property: NEW
main:inbound_property: ABC
Response: XYZ-123-123

Download the source code

This example was about mule sub-flow.

You can download the source code here:

About Author

Ram's expertise lies in test driven development and re-factoring. He is passionate about open source technologies and loves blogging on various java and open-source technologies like spring. You can reach him at [email protected]

Comments are closed.