With Mule 3.7.0, a new modeling and transformation language was introduced, DataWeave. This is more powerful than its predecessor DataMapper which is marked as deprecated in Mule 3.7
DataWeave component appears as “Transform Message” in Mule Anypoint Studio under Mule Palette. DataWeave in Mule 3.7 supports processing of JSON, Java, CSV, EDI, XML, Pojo etc. One format that was missing in DataWeave support was Fixed Width text format. As per the beta release notes of Mule 3.8, DataWeave in Mule 3.8 is going to support fixed width text files. But for many of us, it may not be possible to upgrade Mule server for this.
So How to Process fixed width text file with DataWeave in Mule 3.7?
So for those who use Mule 3.7 with DataWeave and still want to process fixed width text files, here is the workaround for it.
Let’s consider below fixed with sample text file –
001MONSTARTWORK 001TUEPROGRESSWORK 001WEDTAKEABREAK 001THURESUMEWORK 001FRIFINISHWORK 001SATCHILLDOWN 001SUNGRABABEER
Record definition is –
Id - Start Position: 0, length: 3 Day - Start Position: 3, length: 3 Shout - Start Position:6, length: 13
Here is our sample flow that reads the file from input directory, applies dataweave transformation and writes the generated file to output directory.
XML Flow –
<flow name="DW-FixedWidth-Processing"> <file:inbound-endpoint responseTimeout="10000" doc:name="File" moveToDirectory="output" path="input"/> <dw:transform-message doc:name="Transform Message" metadata:id="44c29528-4f2b-4aa6-a454-bf2fe7b8de57"> <dw:input-payload doc:sample="string_1.dwl"/> <dw:set-payload><![CDATA[%dw 1.0 %output application/json --- (payload splitBy "\n") map { Id:$[0..2], Day:$[3..5], Shout:trim $[6..18] } ]]></dw:set-payload> </dw:transform-message> <file:outbound-endpoint path="output" outputPattern="output.txt" responseTimeout="10000" doc:name="File"/> </flow>
Let’s look at the DataWeave code now –
%dw 1.0 %output application/json --- (payload splitBy "\n") map { Id:$[0..2], Day:$[3..5], Shout:$[6..18] }
As our payload is going to be file content i.e. String, we will split the content with new line char “\n”. Note the parenthesis used for `payload splitBy “\n”` which makes the output of that expression, input for map. Now, we have split our payload by newline so inside map we will be reading each line from our file and can be accessed with default alias $.
As per our record definition, Id field starts at 0 and is of 3 character long. So we map our Id by using Range Selector on String $[0..2] which is $[startIndex..endIndex]. Similarly we can select Day and Shout also.
We have intentionally used “\n” instead of “\r\n” to make sure our code works on windows as well as UNIX. Note that, for the last field our actual file content ends at 18th position but on windows formatted files, there should be “\r” at 19th position. As we will only map until last fixed position, “\r” should not be a problem. In case you see carriage returns in output then most probably you have included this last character in your output too.
Now, we have seen how we can split the fields in dataweave. You can actually write any logic on the fields. For example, to avoid any empty spaces in shout field we can use trim function.
shout: trim $[6:18]
Here is our output from above transformation –
[ { "Id": "001", "Day": "MON", "Shout": "STARTWORK" }, { "Id": "001", "Day": "TUE", "Shout": "PROGRESSWORK" }, { "Id": "001", "Day": "WED", "Shout": "TAKEABREAK" }, { "Id": "001", "Day": "THU", "Shout": "RESUMEWORK" }, { "Id": "001", "Day": "FRI", "Shout": "FINISHWORK" }, { "Id": "001", "Day": "SAT", "Shout": "CHILLDOWN" }, { "Id": "001", "Day": "SUN", "Shout": "GRABABEER" } ]
With this example, we learned how to consume fixed width text file with DataWeave in Mule 3.7.
Next see how to create fixed width flat file using DataWeave in Mule 3.7
Feel free to let me know what you think or any questions, I will be happy to help.