Dynamic Flow Invocation

26 May, 2017 | 2 minutes read

Flow reference component is used in Mule flows to send a message to another flow for further processing. When a message reaches a flow reference component in a flow, Mule sends the message to another flow according to the configuration of the flow-ref attributes. A flow reference can route messages to any type of flow within the same application.

flow-ref attributes

The configuration is done in the flow reference component’s Properties Editor:

Flow reference component’s Properties Editor

In order to invoke some flow, the flow name shall be selected from the Flow name drop which is auto-populated with the flow names within the application.

However, the problem appears when the flow should be invoked dynamically at run time based on the context of the message or some configurable parameters. For example, when we have some common framework flow with error handling and logging in it we are invoking some other flows (services).

One solution is to store the sub-flow name in a variable based on the condition and provide that flow variable name as a flow-ref i.e.

<flow-ref name=“#[flowVars.pname]” doc:name=“Call Process”/>

But in this case when we switch from configuration xml to message flow view, if we click on the flow reference component the parameter disappears.

Another solution is using custom interceptors. As stated in the official MuleSoft documentation Mule interceptors are useful for attaching behaviors to multiple components. The interceptor pattern is often referred to as practical AOP (Aspect Oriented Programming), as it allows the developer to intercept processing on an object and potentially alter the processing and outcome.

Interceptor interface should be implemented in order to create a component that will intercept, process, and route the messages in the inbound message flow. It has a single method:

MuleEvent process(MuleEvent event);

The event parameter contains the current message. Developers can extract the current MuleMessage from the event and manipulate it as needed. The process method must return a MuleMessage that will be passed on to the next flow component.

Another important thing here is the configuration of the interceptors i.e. class attribute that references the Interceptor’s implementation Java class:

<custom-interceptor class=“com.interworks.labs.mule.DynamicFlowReference” doc:name=“Dynamic Flow Reference” />

The implementation of our sample dynamic flow reference component is:

package com.interworks.labs.mule;

import org.mule.api.DefaultMuleException;
import org.mule.api.MuleContext;
import org.mule.api.MuleEvent;
import org.mule.api.MuleException;
import org.mule.api.interceptor.Interceptor;
import org.mule.config.i18n.MessageFactory;
import org.mule.construct.Flow;
import org.mule.processor.AbstractInterceptingMessageProcessor;

public class DynamicFlowReference extends AbstractInterceptingMessageProcessor implements Interceptor {

	private MuleContext muleContext;

	public void setMuleContext(MuleContext context) {
		this.muleContext = context;
	}

	public MuleEvent process(MuleEvent event) throws MuleException {
		String flowName = event.getFlowVariable("flow-name");
		Flow flow = null;
		flow = (Flow) muleContext.getRegistry().lookupFlowConstruct(flowName);
		if (flow == null) {
			throw new DefaultMuleException(
					MessageFactory.createStaticMessage(String.format("Flow %s is not defined!", flowName)));
		}
		return processNext(flow.process(event));
	}
}