Flows and Subflows
Mule apps process messages and other parts of Mule events through Mule components, connectors, and modules that are set up within the scope of Flow and Subflow components within an app.
An app can consist of a single flow, or it can break up processing into discrete flows and subflows that you add to the app and connect together. Mule apps in production environments typically use multiple flows and subflows to divide the app into functional modules or for error-handling purposes. For example, one flow might receive a record and transform data into a given format that another flow processes in some special way.
You can connect and trigger their execution with Flow Reference
components or by using the DataWeave
lookup function within expressions and
transformations. The function passes the current event to another flow for
further event processing. You can think of a Flow Reference as a function call that accepts an event as input and then returns the modified event.
Flows can have Mule Sources (such as an HTTP listener receiving a request) that trigger the execution of a flow. For cases where you do not want a source to start a flow right away, you can configure your flow as initially stopped and start it later through Runtime Manager.
Like functions or methods in other programming languages, it is a best practice to focus your flows on specific (perhaps reusable) activities, such as receiving an API request from a web client, processing the event, then returning an appropriate response. If the event processing gets complicated, or must call out to other services, you might factor out that behavior into other flows.
A subflow is a scope that enables you to group event processors in a manner similar to that of a flow, but with certain differences and limitations:
Subflows do not have Mule event sources.
Subflows do not have an error handling scope.
During design, subflows work as macros that replace the Flow Reference components that call them.
When you build the application, all Flow Reference components that call a subflow are replaced by the contents of the referenced subflow.
Referencing subflows results in better performance than referencing a flow.
Because the contents of a subflow replace each Flow Reference component that references that subflow, several instances of the event processors inside that subflow exist in the application at runtime. This behavior can cause issues with event processors that depend on unique IDs or instances to execute, such as batch processors.
For example, configuring a batch job inside a subflow causes the application to fail during deployment if the subflow is referenced from more than one Flow Reference component. The application fails to deploy because multiple instances of a batch job with the same job instance ID exist, which is not allowed.
Each flow (but not subflow) can have its own error handling. One reason for calling a flow through a Flow Reference component is to isolate the error handling to different contexts. For example, a parent flow that receives web client requests might define HTTP-related error handling. If the parent flow then calls a JMS queue for further processing, you can put the JMS event processors in a separate child flow and call that flow with a Flow Reference component. This child flow can then define its own JMS-related error handling. This practice is similar to the way you handle or propagate errors in other programming languages, like Java.
Like a flow or subflow, a Try scope also groups together a sequence of event processors with its own error handling. You can place a Try scope inside a flow or subflow to isolate error handling inside a flow without the need to create a separate flow or subflow. The trade-off is that error handling through a Try scope occurs inline inside the flow, which makes it harder to reuse between other flows or subflows.
In both cases, calling a flow or including a Try scope isolates the error handling, similar to the use of Try-Catch blocks inside Java code. For example, placing JMS queue event processing (described above) in its own flow or within a Try scope results in exactly the same error handling behavior, but the event processors in a Try scope cannot be called from another flow.
Some scopes are available for a flow to branch event processing into separate threads and to allow asynchronous processing of the event at a specific point in the flow, for example, the Scatter-Gather and Async scopes. A Choice router enables you to change the downstream sequence of event processors based on some condition.