1.0 Overview
MuleSoft documentation talks about
types of flows and how they behave during runtime (synchronous or
asynchronous), but it doesn’t talk about the method in which a developer could programmatically
invoke a flow. This article will attempt to bring clarity to this area.
You can programmatically invoke a flow via two methods, you
can do it by transport or by flow reference (figure 1.0 below).
Figure 1.0
I have previously written an article about the relationship
between flow
scopes and mule’s variable types, but that article
is based on the premise of invoking flow through transports. I will not
repeat myself here but instead talk about the contrast between invoking flow by
transport versus invoking flow by reference.
I can only demonstrate this contrast via actual code, the
next few sessions would be a walk through about the code I have created to illustrate
this contrast.
2.0 The Code That Illuminates the Concept
At a glance the complete code that shows the internal
intricate differences between invoking an external flow either by transport or
by reference is as illustrated in Figure 2.0.
Figure 2.0
This mule app has only 3 flows, the shortest flow (the one
right at the bottom of Figure 2.0) is the simulated external flow. The two
other flow above the “ExternalFlow” exists to demonstrate the internal runtime difference
between the invocation methods. Both “InvocationByTransport” and “InvocationByFlowRef”
have all the same message processors, the only difference between the two is
how it passes execution control to the “External” flow.
During runtime “InvocationByTransport” flow passes execution
control to “ExternalFLow” via transport invocation (meaning it is trying to invoke
ExternalFlow by HTTP transport, but “InvocationByFlowRef” flow passes execution
control to “ExternalFlow” by flow references, which means it does not go
through HTTP transport, in short it by passes “ExternalFlows” in bound HTTP Receive
endpoint and go straight in to “ExternalFlow”’s message processors.
The sub-flow at the very top of Figure 2.0 is the groovy
script that prints out all the HTTP parameters, flow variables and session
variables. The code for the groovy script are as per listed in the following
code block.
println
"---------------------------------------------------------------------------"
println "List of inbound
properties ..."
message.getInboundProperty('http.query.params').each{k,v
-> println "${k}:${v}" }
println " "
println "List of outbound
properties ..."
message.getOutboundProperty('http.query.params').each{k,v
-> println "${k}:${v}" }
println " "
println "flowVars :"
println flowVars.randomFlowVariable
println " "
println "sessionVars :"
println
sessionVars.randomSessionVariable
println " "
println "Payload ..."
println message.payload
println
"---------------------------------------------------------------------------"
println " "
return message.payload
|
It is very important to key in the “return message.payload”
statement at the end of the groovy script else you will lose your initial payload.
You can get the full source code from the following link.
3.0 The Test That Will Show You the Truth
If you have downloaded the code in section 2.0, we could now
test it together and analyse the behaviour of both flow invocation methods.
I will use postman for testing the flows for the mentioned
mule application in Figure 2.0. (link to youtube tutorial of
postman).
I am using the same set of parameters and payload to test
both “InvocationByTransport” and “InvocationByFlowRef” flows, listed below
would show how the URL looks like for testing each flow respectively.
·
“InvocationByTransport” - http://localhost:8081/transport?firstname=kian&lastname=ting&topic=invocationbyTransportVSbyFlowRef
·
“InvocationByFlowRef”- http://localhost:8082/flowref?firstname=kian&lastname=ting&topic=invocationbyTransportVSbyFlowRef
Figure 3.0 shows what postman would look like when testing
both different invocation methods.
We will test the flows respectively with a POST request and
with the payload of “Test Payload”, the query parameters that you will key in
will remain the same for both flow URLs.
We want to post request for the two different invocation
methods so that we could collate the console logs and look at the contrasting
difference.
The Anypoint Studio console logs will show us what really is
happening behind the scenes.
3.1 Analysing the Test Results
If you use
postman to execute a post request to the respective URLs you will get the two
respective logs as described by the following table. The right most column
shows the execution log for "InvocationByFlowRef" and the second right most column shows the execution
result for "InvocationByTransport" mule flow.
The following table
illustraited the log content that has been churned out via our testing
activities. This table is segregated into 3 segments the first segment (1)
shows the log messages spit out by the main flow, the second segment (2) shows
the log message spit out by the "ExternalFlow" when execution control
is relayed to it via the main flow. Finally the last segment (3) shows the logs
messages that is generated by the main flow when execution control is retuned
back to it from the "ExternalFlow".
Execution Control
|
Invocation by transport
|
Invocation by Flow Reference
|
(1) Main Flow
|
INFO 2017-06-07 21:42:35,497
[[flowrefvstransportinvocation].HTTP_8081.worker.01]
org.mule.api.processor.LoggerMessageProcessor: (Invocation By Transport)
Before Invocaiton : ---------------------------------------------------------------------------
---------------------------------------------------------------------------
List of inbound
properties ...
lastname:ting
firstname:kian
topic:invocationbyTransportVSbyFlowRef
List of outbound
properties ...
lastname:ting
firstname:kian
topic:invocationbyTransportVSbyFlowRef
flowVars :
randomFlowVariable
sessionVars :
randomSessionVariable
Payload ...
Test Payload
-------------------------------------------------------
|
INFO 2017-06-07 21:43:56,901
[[flowrefvstransportinvocation].HTTP_8082.worker.01]
org.mule.api.processor.LoggerMessageProcessor: (Invocation By FlowRef) Before
Invocaiton :
---------------------------------------------------------------------------
---------------------------------------------------------------------------
List of inbound
properties ...
lastname:ting
firstname:kian
topic:invocationbyTransportVSbyFlowRef
List of outbound
properties ...
lastname:ting
firstname:kian
topic:invocationbyTransportVSbyFlowRef
flowVars :
randomFlowVariable
sessionVars :
randomSessionVariable
Payload ...
Test Payload
-------------------------------------------------------
|
(2) External Flow
|
INFO 2017-06-07 21:42:35,934
[[flowrefvstransportinvocation].HTTP_8083.worker.01]
org.mule.api.processor.LoggerMessageProcessor: (External Flow) Initial Invocation Settings :
--------------------------------------------------------------------------
List of inbound
properties ...
List of outbound
properties ...
flowVars :
null
sessionVars :
null
Payload ...
Test Payload
-------------------------------------------------------
|
INFO 2017-06-07 21:43:56,915
[[flowrefvstransportinvocation].HTTP_8082.worker.01]
org.mule.api.processor.LoggerMessageProcessor: (External Flow) Initial Invocation Settings :
--------------------------------------------------------------------------
List of inbound
properties ...
lastname:ting
firstname:kian
topic:invocationbyTransportVSbyFlowRef
List of outbound
properties ...
lastname:ting
firstname:kian
topic:invocationbyTransportVSbyFlowRef
flowVars :
randomFlowVariable
sessionVars :
randomSessionVariable
Payload ...
Test Payload
-------------------------------------------------------
|
(3) Back In Main Flow
|
INFO 2017-06-07 21:42:35,989
[[flowrefvstransportinvocation].HTTP_8081.worker.01]
org.mule.api.processor.LoggerMessageProcessor: (Invocation By Transport)
After Invocaiton : ---------------------------------------------------------------------------
---------------------------------------------------------------------------
List of inbound
properties ...
List of outbound
properties ...
flowVars :
randomFlowVariable
sessionVars :
randomSessionVariable
Payload ...
Test Payload + "appended string from
ExternalFlow ..."
-------------------------------------------------------
|
INFO 2017-06-07 21:43:56,918
[[flowrefvstransportinvocation].HTTP_8082.worker.01]
org.mule.api.processor.LoggerMessageProcessor: (Invocation By FlowRef) After
Invocaiton : ---------------------------------------------------------------------------
---------------------------------------------------------------------------
List of inbound
properties ...
lastname:ting
firstname:kian
topic:invocationbyTransportVSbyFlowRef
List of outbound
properties ...
lastname:ting
firstname:kian
topic:invocationbyTransportVSbyFlowRef
flowVars :
randomFlowVariable
sessionVars :
randomSessionVariable
Payload ...
Test Payload + "appended string from
ExternalFlow ..."
---------------------------------------------------------------------------
|
Both "InvocationByTransport" (second left column) and "InvocationByFlowRef" (left most
column) starts out the same in segment (1), both of them have the same set of
flow variable, session variable, inbound and outbound properties, both even
have the same payload.
Segment (2) of
the log is where things start to look interesting, "InvocationByTransport" flow relays
execution control to “ExternalFlow” via HTTP transport which differs to “InvocationByFlowRef” which relays
control to “ExternalFlow” by way of “Flow Reference”. Relaying execution
control by way of transport will only have the test payload preserved, which
mean in other word “ExternalFlow” can only access the paylod of “InvocationByTransport”. If execution control
is relayed by “Flow Reference”, everything is preserved, and the external flow
could still access the flow variables, session variables, inbound and outbound
properties of “InvocationByFlowRef”.
The last
segment (3) of the console log shows variable and property values that are
still accessible by the main calling flow. If execution is relayed back from “ExternalFlow”
via HTTP response transport (second left column) you will see that all inbound
and outbound properties are lost, only the initially created flow and session
variables are still accessible. Contrary to the relaying back control from “Flow
Reference” (left most column), we are able to see that everything is preserved,
the initial inbound and outbound properties of the main flow is still
accessible and so are the flow and session variables.
4.0 Conclusion
It is always good to have a conclusion pertaining to an
experiment, the following table summarizes my conclusion pertaining to flow execution
by transport or by flow reference.
From the table we could conclude the behaviour of invocation
by “Flow Reference” is analogous to treating the target external flow as part
of the main flow, and whatever property or variables is created in the main
flow is still accessible via the invoked external flow.
Execution Scope
|
Execution by Transport
|
Execution by “Flow Reference”
|
||||||||||||||||||||||||
When Execution Control is passed to Target External Flow
|
|
|
||||||||||||||||||||||||
When Execution Control is passed back to calling flow
|
|
|
Thanks for sharing this useful blog with us.
ReplyDeleteMulesoft Online Training
Mulesoft Training in Hyderabad
Thanks for sharing valuable information and very well explained. Keep posting.
ReplyDeletemule 4 online training
mulesoft online course