Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

MuleSoft Programmatically Invoking Flows

DZone's Guide to

MuleSoft Programmatically Invoking Flows

This experiment in Mule flows looks at the behavior of flows and shows how to programmatically invoke a flow via the transport and flow reference methods.

· Integration Zone ·
Free Resource

The new Gartner Critical Capabilities report explains how APIs and microservices enable digital leaders to deliver better B2B, open banking and mobile projects.

1.0 Overview

The 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, by transport or by flow reference (figure 1.0 below).

Image title

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; instead I'll talk about the contrast between invoking a flow by transport versus invoking a flow by reference.

I can only demonstrate this contrast via actual code, sothe 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.

Image title

Figure 2.0.

This mule app has only three flows. The shortest flow (the one right at the bottom of Figure 2.0) is the simulated external flow. The two other flows above the “ExternalFlow” exist 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, the “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 bypasses “ExternalFlow's” inbound HTTP Receive endpoint and goes straight into “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 is 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 Github.

3.0 The Test That Will Show You the Truth

If you have downloaded the code in section 2.0, we can now test it together and analyze the behavior of both flow invocation methods.

I will use Postman for testing the flows for the Mule application mentioned in Figure 2.0 (you can use this Youtube tutorial for Postman). 

I am using the same set of parameters and payload to test both the “InvocationByTransport” and “InvocationByFlowRef” flows; below is 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.

    Image title

    Figure 3.0.

    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 can 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 the "InvocationByTransport" Mule flow.

    The following table illustrates the log content that has been churned out via our testing activities. This table is segregated into three segments. The first segment (1) shows the log messages spit out by the main flow, and 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) start out the same in segment (1); both of them have the same set of flow variable, session variable, inbound and outbound properties, even 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 means “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.

    Execution Scope

    Execution by Transport

    Execution by “Flow Reference”

    When Execution Control is passed to Target External Flow

    Property Type

    Is Accessible

    Flow Variables

    N

    Session Variables

    N

    Inbound Properties

    N

    Outbound Properties

    N

    Payload

    Y

    Property Type

    Is Accessible

    Flow Variables

    Y

    Session Variables

    Y

    Inbound Properties

    Y

    Outbound Properties

    Y

    Payload

    Y

    When Execution Control is passed back to calling flow

    Property Type

    Is Accessible

    Flow Variables

    Y

    Session Variables

    Y

    Inbound Properties

    N

    Outbound Properties

    N

    Payload

    Y

    Property Type

    Is Accessible

    Flow Variables

    Y

    Session Variables

    Y

    Inbound Properties

    Y

    Outbound Properties

    Y

    Payload

    Y

    From this table, we can conclude that the behaviour of the invocation by “Flow Reference” is analogous to treating the target external flow as part of the main flow, and whatever property or variables are created in the main flow are still accessible via the invoked external flow.

    The new Gartner Critical Capabilities for Full Lifecycle API Management report shows how CA Technologies helps digital leaders with their B2B, open banking, and mobile initiatives. Get your copy from CA Technologies.

    Topics:
    mulesoft ,transport ,mule flow ,integration ,tutorial

    Opinions expressed by DZone contributors are their own.

    {{ parent.title || parent.header.title}}

    {{ parent.tldr }}

    {{ parent.urlSource.name }}