Use Mule Data Mapper to enrich an existing payload - mule

i have a Mule flow that gathers calculations information from an external service to enrich a list of Invoices. So, I end up (after the enricher scope) with my calc info in a flow variable, and my original invoices in the payload.
Can I use the data mapper to inject my calculation values into the existing invoice objects?
Currently I'm using a Groovy script - but prefer config over scripting.

You can use the datamapper transformer within an enricher scope to enrich parts of the payload.
The enricher can enrich the payload if you set the 'target' to a named field on a POJO for example, or if your payload is a Map, the enricher will add a new entry to the Map.
<enricher>
<datamapper... />
<enrich target="#[payload.field1]" source="#[payload.datamapperoutputfield1]" />
<enrich target="#[payload.field2]" source="#[payload.datamapperoutputfield1]" />
</enricher>

Related

How to use Mule Expression Language for dynamic spring property injection

<set-variable variableName="template" value="#[payload.templatePath]" doc:name="Template Path"/>
<custom-transformer class="com.comviva.mfs.eig.transformers.generic.MapUtil" doc:name="Map">
<spring:property name="sessionBean" ref="SessionBean"/>
<spring:property name="fixedTemplatePath" value="#[flowVars['template']]"/>
OR In both cases I want the value of the map to be replaced dynamically while sending the data as the key templatePath contains dynamic value and I want that to get picked from the payload that is of Map type
<custom-transformer class="com.comviva.mfs.eig.transformers.generic.MapUtil" doc:name="Map">
<spring:property name="sessionBean" ref="SessionBean"/>
<spring:property name="fixedTemplatePath" value="#[payload.templatePath]"/>
Spring properties are not interpreted by the MEL. As it is provided as setter injection which is invoked during instantiation the value of payload or a flow/session var will not be available.
You can change the transformer code to read the value from the payload within the transformation code itself as payload will be available from 'Object src' param.

Mule: return the original message to flow (like For Each)

In For Each introdution we have: "The Foreach scope splits a collection into elements and processes them iteratively through the processors embedded in the scope, then returns the original message to the flow."
I would like to know if we have a form to return the original message to the flow when on the middle of the flow we have a processing with new message (payload) similar For Each works, but it is not a case to use For Each!
Example:
Flow (payload AA) -> ["Sub" flow (payload BB)] -> Flow (payload AA)
Is there a form to do this?
The simplest way is to use an enricher that stores the result of the sub-flow in a flowVar so that the original payload is not modified:
<enricher target="#[flowVars.someSubFlowResult]">
<flow-ref name="mySubFlow" />
</enricher>
Or alternatively manually store the original payload into a flow variable on entering the flow and at the end of the flow set the payload back to the original payload using the flow variable. For example:
<set-variable variableName="originalPayload" value="#[payload]" />
<!-- do some other processing -->
<set-payload value="#[flowVars.originalPayload]" />

How to enrich the response from original payload

I want to enrich my message (POJO) properties from original payload stored in flow variable
<set-variable variableName="SupplierRequest" value="#[payload]" doc:name="SupReq"/>
<flow-ref name="GetSupplierRequestDetail" doc:name="GetReqData"/>
<set-variable variableName="SupplierRequestData" value="#[payload]" doc:name="SupReqData"/>
In above code, I need couple of SupplierRequestData POJO properties to be set with properties from SupplierRequest POJO.
Do I need to write custom transformer or any other solution?
Ideally you should use the enritcher. But given that you already have the original payload in a flow variable you could just use an expression component as an expression transformer would imply a transformation from A to B while this is modification of A with B:
<expression-component><![CDATA[message.payload.propertyName = flowVars.myOrigPayload.myProp]]></expression-component>

Mule ESB: File outputpattern doesn't translate the pattern

I'm using Mule ESB CE 3.4. I have a requirement where I'm reading the configuration information from database and using it as the file name for the file outbound endpoint. Here is an example code (the code may not work as I have only given an outline)
<file:connector name="File-Data" autoDelete="false" streaming="true" validateConnections="true" doc:name="File" />
.....
<!-- Gets the configuration from database using a transformer. The transformer populates the configuration entries in a POJO and puts that in a session. -->
<custom-transformer class="com.test.DbGetConfigsTransformer" doc:name="Get Integration Configs"/>
....<!-- some code to process data -->
<logger message="$$$: #[sessionVars['currentFeed'].getFilePattern()]" doc:name="Set JSON File Name" /> -->
<file:outbound-endpoint path="/temp" outputPattern="#[sessionVars['currentFeed'].getFilePattern()]" responseTimeout="10000" mimeType="text/plain" connector-ref="File-Data" doc:name="Save File"/>
The above code throws the following error:
1. The filename, directory name, or volume label syntax is incorrect (java.io.IOException)
java.io.WinNTFileSystem:-2 (null)
2. Unable to create a canonical file for /temp/Test_User_#[function:datestamp:YYYYMMddhhmmss.sss] (org.mule.api.MuleRuntimeException)
org.mule.util.FileUtils:354 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/MuleRuntimeException.html)
3. Failed to route event via endpoint: DefaultOutboundEndpoint{endpointUri=file:///temp, connector=FileConnector
In the database table, the field name is called FilePattern and it has the value 'Test_User_#[function:datestamp:YYYYMMddhhmmss.sss]. If I hardcode the value or move this value to the mule configuration file
file.name=Test_User_#[function:datestamp:YYYYMMddhhmmss.sss]
and use the configuration property syntax (for e.g. ${file.name} in the 'outputpattern'), it works. But if I read the same from db and use it, it is not working and throwing the error. The logger displays as (which is read from the db)
$$$: Test_#[function:datestamp:YYYYMMddhhmmss.sss]
Any help is much appreciated.
If your datestamp format does not vary, you should just store the environment prefix in your db and use something like:
outputPattern="#[sessionVars['prefix']+server.dateTime.format('YYYYMMddhhmmss.sss')]"
If you need to use your current database values, you can use basic Java string methods to find the correct substrings. For example:
#[sessionVars['currentFeed'].getFilePattern().substring(0,sessionVars['currentFeed'].getFilePattern().indexOf('function')-2)+server.dateTime.format('YYYYMMddhhmmss.sss')]
If you use different datestamp formats, you can find that part as well using similar String methods. However, I still suggest you come up with an implementation that only stores the environment prefix in the db.

Mule Message Enricher Target Expression

I have a flow that takes a pair of dates inbound and then uses a message enricher to get a list of employees that worked on a specific job between those two dates. The result is a simple list of maps returned from a JDBC database. I got that saved into a flow variable without any trouble. The next enrichment is causing me trouble. I setup a for each loop that uses the employees list from the flow variable. This works great and I then need to execute another JDBC query for each of these employees to get all the time tickets they turned in between the two dates passed to the flow. The query works but I am having trouble defining the target expression to hold the result. I would like to see the target be a map with the employee id as the key and the tickets for the period (list of maps) be the value. Is there any way to do this? Is there a better way to save these results? After I get all the tickets, I need to summarize them in various ways and generate a report showing the detail as well as the analysis.
I am currently developing this in mule studio for the community runtime version 3.4.
Is this like something that you are looking for?
<set-variable variableName="maplistmap" value="#[new java.util.HashMap()]"/>
<foreach>
<jdbc-ee:outbound-endpoint exchange-pattern="request-response" queryKey="selekt" queryTimeout="-1" connector-ref="Database">
<jdbc-ee:query key="selekt" value="select * from mytable where id = #[payload]"/>
</jdbc-ee:outbound-endpoint>
<scripting:component>
<scripting:script engine="Groovy"><![CDATA[
flowVars["maplistmap"].put(payload[0].id, payload)
]]></scripting:script>
</scripting:component>
</foreach>
<logger message="#[flowVars.maplistmap]" level="INFO"/>