Integration & IT Modernization

# Mule Variable Scopes and Passing Global Values with Mule Registry

Mule variables and their scope are a widely-discussed subject.

Even with the official document (linked above) and plenty of online discussions, I still find there are subtleties left to be discovered. Sometimes it takes experimenting to find out the precise behavior.

This is how I sum up the general rules concerning variables and scopes:

• Flow variable is “global” to all flows, except for flows with the transport barrier (this appears to contradict Mule official document which states “flow variable does not carry over to the next flow or application”).
• Session variable is also “global” to all flows, it can even go past transport barriers.
• Even session variable has a limit. When that happens, we need to find out other mechanisms to pass around global values.

In this post, we’ll use a full example to demonstrate the general rules of flow and session variables, and how to pass around global values with Mule registry.

We’ll first go over each of the four flows in the demo application, then we’ll show the run time output. We’ll discuss some subtleties and caveats when using different type of variables. The full source code is listed at the end.

As illustrated by the flow diagram, there are four flows in the demo project:

1. “main-http-flow”: This flow is invoked by http endpoint. It first sets the payload, then sets a flow variable “fvar”, a session variable “svar”, then it stores a string value using the application registry (see #4 below).
2. “regular-flow”: This is regular flow without a transport barrier. The main flow invokes this one directly, so all three variables are accessible here. It shows that flow variables are actually “global” to other regular flows.
3. “vm-flow”: This flow uses VM inbound transport, the main-http-flow “invokes” this flow with a VM outbound transport. Please note, there is no explicit “invoke” (I call it implicit invoke). The main flow just sends a message to the outbound VM. Therefore, there is a transport barrier between these two flows. As the output shows, the flow variable “fvar” is blocked by the transport barrier. The session variable “svar” can penetrate the transport barrier and is accessible here. The registry is also available in this flow.
4. “file-flow”: This last flow is running independently on its own. It is not invoked explicitly nor implicitly by anyone. This flow is triggered when a file is dropped into the “c:/dev/” in folder. As the output shows, neither flow variable or session variable defined in the main-http flow are accessible here. Since neither flow nor session variable is accessible from the main flow, in order to share the global value from the main-http flow to here, we ended up using the Mule registry. For more details about Mule registry, click here.

Run time output:

**** main-http-flow, fvar=foo, svar=sss, rvar=Roar!, payload=main flow msg
**** regular flow, everything is safe, fvar=foo, svar=sss, rvar=Roar!, payload=main flow msg
**** vm flow, flowVar not safe, fvar=null, svar=sss, rvar=Roar!, payload=main flow msg
**** file flow, only registry is good, fvar=null, svar=null, rvar=Roar!

A few notes about the source code:

• If you are unsure whether a variable exists, the safe way to reference the variable is to use the syntax #[?fvar], so you won’t get an exception if the #[fvar] is null.
• I noticed that setting the registry (muleContext.getRegistry().registerObject(“rvar”, new String(“Roar!”)) somehow truncates the payload. So I placed this line inside “message enricher” to keep the original payload intact.
• Finally, using Mule registry is one way to share global values. There are other ways, such as object store, global file or even database. You can choose whichever one fits your application the best.

Here is the full source:

<file:connector name="File" autoDelete="true" streaming="true" validateConnections="true" doc:name="File"/>
<file:connector name="File1" autoDelete="true" streaming="true" validateConnections="true" doc:name="File"/>
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration"/>
<vm:connector name="VM" validateConnections="true" doc:name="VM"/>
<flow name="main-http-flow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/scope" doc:name="HTTP"/>
<set-variable variableName="fvar" value="foo" doc:name="flow fvar"/>
<set-session-variable variableName="svar" value="sss" doc:name="Session svar"/>
<enricher target="junk" doc:name="Message Enricher">
<scripting:component doc:name="AppRegistry-rvar">
<scripting:script engine="Groovy"><![CDATA[muleContext.getRegistry().registerObject("rvar", new String("Roar!"))]]></scripting:script>
</scripting:component>
</enricher>
<flow-ref name="regular-flow" doc:name="regular-flow"/>
<vm:outbound-endpoint exchange-pattern="one-way" path="/testq" connector-ref="VM" doc:name="VM"/>
</flow>
<flow name="regular-flow">
<logger message="**** regular flow, everything is safe, fvar=#[fvar], svar=#[svar], rvar=#[app.registry.get('rvar')], payload=#[payload]" level="INFO" doc:name="regularLogger"/>
</flow>
<flow name="vm-flow">
<vm:inbound-endpoint exchange-pattern="one-way" path="/testq" connector-ref="VM" doc:name="VM"/>
<logger message="**** vm flow, flowVar not safe, fvar=#[?fvar], svar=#[svar], rvar=#[app.registry.get('rvar')], payload=#[payload]" level="INFO" doc:name="vm_Logger"/>
</flow>
<flow name="file-flow">
<file:inbound-endpoint path="c:\dev\in" connector-ref="File" responseTimeout="10000" doc:name="File"/>
<logger message="**** file flow, only registry is good, fvar=#[?fvar], svar=#[?svar], rvar=#[app.registry.get('rvar')]" level="INFO" doc:name="file_Logger"/>
<file:outbound-endpoint path="c:/dev/out" connector-ref="File1" responseTimeout="10000" doc:name="File"/>
</flow>


This site uses Akismet to reduce spam. Learn how your comment data is processed.

##### Yuan Meng

More from this Author