Mule modularising/invoking private and sub flows - mule

I am modularising my mule configuration into multiple private and sub flows for common tasks such as a common notification/logging flow for example.
These flows require multiple different pieces of information in order to be invoked from various different flows.
What is the best practice to pass this information to the private/sub modularised flow?
Is it flow variables? session variables? create a map of these values as the payload?
I am currently using flow variables, but this makes the configuration very verbose.
Taking my logging flow as an example, I have multiple set-variable processors followed a flow-ref multiple times:
<set-variable variableName="loggingEndpoint" value="xx" />
<set-variable variableName="loggingPriority" value="INFO" />
<set-variable variableName="loggingSubject"
value="xxx" />
<set-variable variableName="loggingBody"
value="xxxxx" />
<set-variable variableName="loggingCC"
value="xx" />
<flow-ref name="LoggingService" doc:name="Logging service" />
I do this multiple times so theres a lot of XML. But if flowVars is the best way to pass info to a private flow then I don't mind. Just want to know best practice.

For logging purposes I would use a logging interceptor, as explained here:
http://www.mulesoft.org/documentation/display/current/Using+Interceptors
http://www.mulesoft.org/documentation/display/current/Java+Component+Reference
If you have something more general, like sending an email or persisting info in a database you can put a and send information in session variables. This way those time consuming tasks do not block your main flow.
Regards.

Related

Calling a flow using Groovy Script in Mule 4

I need to make a call to a flow using groovy script in mule 4. Can someone let me know if they have tried it using Mule 4
It is possible, but I would HIGHLY recommend that you do NOT do it.
You will have to dig deep down into the Mule Java APIs and couple yourself to them and also add a lot of your own error handling etc. and be wary of platform updates and the if the Java API changes.
Personally I would restructure you app to only have 'business logic' in scripts and let Mule do the flow lookups elsewhere.
You can even lookup flows in dataweave.
But here is a rough working example(Note you will have to harden this code yourself):
<flow name="test-flow">
<scheduler>
<scheduling-strategy>
<fixed-frequency frequency="100000"></fixed-frequency>
</scheduling-strategy>
</scheduler>
<set-payload value="bla bla" />
<scripting:execute engine="groovy" doc:name="Toggle flow" doc:id="2eb6f071-bdef-4d3d-926d-2565fcd62d33">
<scripting:code>
import org.mule.runtime.api.message.Message;
import org.mule.runtime.core.api.event.CoreEvent;
import org.mule.runtime.core.api.event.EventContextFactory;
flow=registry.lookupByName("another-flow").get();
thisflow=registry.lookupByName("test-flow").get();
msg = Message.builder().value(payload).build();
event =CoreEvent.builder(EventContextFactory.create(thisflow,
org.mule.runtime.dsl.api.component.config.DefaultComponentLocation.fromSingleComponent("add-location"))).message(msg).build();
result =flow.process(event);
</scripting:code>
</scripting:execute>
</flow>
<flow name="another-flow">
<logger level="ERROR" message="Another Flow #[payload]" />
</flow>
You need to fetch the current flow and the flow you want to call.
Using the Mule APIs - construct a Mule Event, Messgae, payload etc. You will also need to add any attributes you need etc.
Is there any way to call mule "static flow" like When I use the above groovy script and it will call the flow ( its starting the called flow and get the values) and get the values.
Requirement :
Like, Mule Flow A is running independently.
Mule flow B wants to access the Flow A variable with out starting the flow A using groovy or python Script.
Note: Can do with flow reference and lookup but would like to implement using script.

How to make a call to multiple rest service in mulesoft

I have a requirement where i need to call multiple rest service.
currently I am invoking only one rest service, as the file is huge we have splitted into parts (like 1 to 10k , 10k to 20k, 20k to 30k...so on)
the flow is designed to read the complete file and now it has been splitted.
Flow goes like this:
HTTP requester(WS call)----businesslogic.
I want to invoke multiple services(1 to 10k , 10k to 20k, 20k to 30k...so on )and use the same common business logic flow.
how to configure?
If you need to call rest api's in sequence for every record the you can do that inside batch steps.
If you need to make rest api call's with out any sequence then you can use scatter gather inside batch.
Number of records to be processed in parallel can be set by configuring batch size.
References: https://docs.mulesoft.com/mule-user-guide/v/3.6/scatter-gather
https://dzone.com/articles/part-1-mule-batch-processing-introduction
Mule allows this by using the scatter-gather component. Be aware of exception handling in this use case. In case one or more routes fails, you need to control this.
<scatter-gather timeout="6000">
<!-- custom-aggregation-strategy class="implement and place your class here if you need a custom strategy"/-->
<http:request config-ref="requestConfig1" path="/path1" method="POST" doc:name="HTTP"/>
<http:request config-ref="requestConfig2" path="/path2" method="POST" doc:name="HTTP"/>
<http:request config-ref="requestConfig3" path="/path3" method="POST" doc:name="HTTP"/>
</scatter-gather>

How to loop over the keys/values of a objectstore in mule flow

I want to iterate over all the values of the objectstore entries and log them in a mule flow. I am trying to do something like this -- is this correct or there is something better. I don't want to use java.
<objectstore:allkeys config-ref="ObjectStore" targetProperty="PropertyKey" targetScope="SESSION"/>
<foreach collection="#[PropertyKey]" doc:name="Splitting Locations_XML into chunks">
<logger message="Key--#[payload]" level="INFO" doc:name="Logger"/>
<objectstore:retrieve key="#[payload]" config-ref="ObjectStore" targetProperty="PropertyValue" targetScope="SESSION"/>
<logger message="Value--#[payload]" level="INFO" doc:name="Logger"/>
</foreach>
I would argue that you are trying to shoe horn essentially procedural code into a pipes and filters pattern use flow processors for use cases which naturally call out for pipes and filters and encapsulate procedural logic within components and then include the component within the flow. Avoid writing procedural logic using Mule constructs. I know like most design issues there is some grey area but in most cases a best practice can be agreed upon.
From a purely implementation view point this does look valid.

Is there a way to mock non-global filters in a sub-flow using MUnit?

I wanted to know if there was a way to mock a custom-filter that is within a sub-flow using MUnit.
I'm using Mule 3.4.0 and MUnit 3.4.0.M5.
The sample flow looks like the following.
<sub-flow name="a">
<choice>
<when expression="something...">
<custom-filter doc:name="filter a">...</custom-filter>
</when>
<otherwise>
...
</otherwise>
</choice>
</sub-flow>
I've had to create a wrapper flow around the subflow because I get a NullPointerException whenever I try to hit the sub flow directly using the runFlow syntax. However, in doing so, I am unable to mock the custom-filter using the whenMessageProcessor syntax. Please see my attempt below.
whenMessageProcessor("custom-filter"
.withAttributes(attribute("name").ofNamespace("doc").withValue("filter a"))
.thenReturn(muleMessageWithPayload("some response");
This results in the message not being mocked.
There are to issues here mixed up.
You having to wrap you sub-flow is a MUnit/Mule issue as commented here:
How to mock a Java component within Mule Flow using MUnit
The second issue is filter mocking. Short answer is you can not, please check:
https://github.com/mulesoft/munit/issues/108
Conceptually a filter is a shorthanded way of doing a choice (or an if in a normal language). One usually does not mock a choice/if it rather changes a value in a variable or in our case in the mule message payload. That's why the filter MP can not be mocked.
HTH

How to retain inbound properties across transport barrier

I am building a restful proxy using mule where I have a need to call two web services in a single flow. The call to the first WS is supposed to do user authentication and if the authentication succeeds, then the ORIGINAL HTTP request will be proxied to the correct REST end point by a second WS call. I have a problem after the first authentication web service call returns. When this call returns, the original HTTP request is lost.
How do I retain the original HTTP request that comes in, save it across the first authentication web service call and then set the original headers just before the second web service call?
Please suggest to me the right approach to achieve this.
I would suggest to go with enricher in this case.
The scenario here looks like the first call is only to authenticate. So use and enricher to call the first WS and save the response as a flow varaible.
This way u still have your payload and all the properties same as they came in from the original request. You can the enriched flow varaible to decide on whether to call the second WS or not.
Here is a sample flow.
<flow>
<http:inbound ... />
...
<enricher target="#[variable:authenticationSuccessful]" source="#[payload]" >
<processor-chain>
<!-- YOu call to first WS and then the status whether authentication is succesful or not.
</processor-chain>
</enricher>
<choice>
<when expression="#[flowVars['authenticationSuccessful']]" />
<http:outbound to second WS />
</when>
<otherwise>
<logger level="INFO" message="Authentication Failed" />
</otherwise>
</choice>
</flow>
Hope this helps.
save the original request in flow variable before the first web-service call.
After first web-service call drag set-payload component to flow and assign the value to it from the flow variable which contains the original request.
As Mohan suggested save the inbound properties in variables..
There are 2 type of variables in Mule :- 1) Flow Variables 2) Session variables
So as per your requirement if you want to retain your inbound properties across the transport barrier then use Session variable as it is global and can be used in any of the flows
Flow variables on the other hand in local to the flow in which it is defined..
You can check this to see how to save in a variable :- http://www.mulesoft.org/documentation/display/current/Variable+Transformer+Reference
As the Mohan and Anirban suggested, you're able to make use of flow variables or session variables to keep a reference to your HTTP request. I suggest using flow variables since session variables are serialized and sent off as part of the message.
You can also make use of the enricher scope to "enrich" your current Mule message with the data from the first HTTP request.