How to use MEL in dataweave to replace characters in a string - mule

I am using Anypoint Studio 6.1 and Mule 3.8.1 and have this MEL expression that replaces any text \n with a new line/carriage return.
payload.replace('\\n', System.getProperty('line.separator'))
I would like to move this functionality into Dataweave but cannot get the MEL expression to work or find a way to do this in Dataweave.
How can I reuse the MEL expression in Dataweave?
Thanks

You should investigate Global Functions
Like:
<configuration doc:name="Global MEL-Functions">
<expression-language>
<global-functions file="mel/extraFunctions.mvel">
</global-functions>
</expression-language>
</configuration>
And create your the global function in a resoruce file for reuse
def UUID() {
return java.util.UUID.randomUUID().toString();
}
def decode(value) {
return java.util.Base64.getDecoder().decode(value);
}
def encode(value) {
return java.util.Base64.getEncoder().encodeToString(value.getBytes());
}
def stringToAscii(value) {
StringBuilder sb = new StringBuilder();
for (char c : value.toCharArray())sb.append((int)c);
return new BigInteger(sb.toString());
}
And reference your global functions in your dataweave
payload map
{
target: stringToAscii($) as :string
}

DW is its own mini-language within Mule aside from MEL is how it was described to me and uses a different syntax to do what you are trying. I have not done new lines specifically as my DW expressions use line separators as record separators, but the same general tactic should work. Here is an example of changing commas to spaces within a dw payload mapping:
AcctID: $.ACCOUNT_ID replace "," with " ",

Related

Mule esb 3.8 how to add variable into payload?

let say I have payload:
{ Name=User1, Age=29 }
and variable:
{ Address=Planet Earth}
I want to have a check if that variable not null then add it into payload.
So final result will be:
{ Name=User1, Age=29, Address=Planet Earth }
How? Was try via payload.Put(variable) but that not allow me such.
With DataWeave using a Transform component you can use the expression: payload ++ flowVars.variable
If you don't want or can't use DataWeave then you can use a MEL expression that uses the Java method Map.putAll() of the Map interface. You can not use <set-payload> because it doesn't return a value. Instead you can use the <expression-component> component.
Example:
<expression-component doc:name="Expression"><![CDATA[payload.putAll(flowVars.variable)]]></expression-component>

How to set array property value in code using Carina Test Framework for API tests?

I have the following request json body:
{
...
"attachmentIds": "${attachments}"
...
}
I have a properties file that includes the declaration of the corresponding placeholder
I want to set array of strings in code instead of "attachments" placeholder, but getProperties().setProperty() expects only string value.
How can I achieve it other way or is it possible at all?
Thanks!
As an option you can transform your array into the String in java code. And then pass this String as property value.
Another option, you can pass String array from code and then parse it in your json template.
For example:
String[] arr = { "1", "2", "3" };
apiMethod.addProperty("attachments", arr);
And then in your json:
{
"attachmentIds": [<#list attachments as val>"${val}"<#if val?has_next>,</#if></#list>]
}
Check freemarker documentation to get more details:
https://freemarker.apache.org/docs/ref_builtins_loop_var.html
Also please note that some of freemarker functions (including has_next) are available only in newest versions of library. So make sure to add into your dependencies list. Carina is now in process of migrating to latest freemarker version.

How to use for inside IntelliJ Live Template?

I am trying to write a simple Groovy script which concatenates strings.
This Groovy script is intended to be used as a variable inside an IntelliJ Live Template and generate some code.
When I set the $variableResolvedWithGroovyScript$ to have the following value:
groovyScript("def elements=[\"firstElem\",\"secondElem\",\"thirdElem\"];
String result=\"\";
for (String element : elements) {
result=result+element;
}
return result;"
, clipboard())
I get below error:
startup failed:
Script1.groovy: 1: expecting EOF, found 'return' # line 1, column 183.
lt+element; } return res
^
1 error
However, if I try and remove the for braces({ and }) it works without any problems:
groovyScript("def elements=[\"firstElem\",\"secondElem\",\"thirdElem\"];
String result=\"\";
for (String element : elements)
result=result+element;
return result;"
, clipboard())
If I take above script and run it inside a Groovy Console it works without problems, so I assume this is a Live Template issue.
I tried to escape the braces in the same way the quotation marks are escaped, but without any luck.
How can I write a for(containing more than one instruction) inside of a Live Template ?
I managed to make it work by loading the Groovy script from the disk. So instead of the $variableResolvedWithGroovyScript$'s value, which was:
groovyScript("def elements=[\"firstElem\",\"secondElem\",\"thirdElem\"];
String result=\"\";
for (String element : elements) {
result=result+element;
}
return result;"
, clipboard())
I simply used:
groovyScript("d:\\Some\\Path\\Concatenate.groovy" , clipboard())
The d:\Some\Path\Concatenate.groovy worked with braces and I was also able to define new methods and so on.

mule : Merge List of maps into single Map

I have scattergather in my flow, the output of which is a List of Maps, How can I convert that into a single Map in mule?
I have tried combine-collections-transfomer, flatten payload. Nothing seems to be working.
You can you following dataweave code, but it will override duplicate keys
%dw 1.0
%output application/java
---
{(payload)}
Hope this helps.
I would recommend using a custom Java Transformer so you can easily handle special situations such as duplicate keys with different values. A DataWeave function may also be able to do the trick, but you'll need Mule EE.
With a Transformer it's a simple question of Java code:
public class MyMapFlattener extends AbstractMessageTransformer{
public Object transformMessage(MuleMessage message, String outputEncoding) throws TransformerException {
//assuming your payload is the list of map
List<Map<?, ?>> listOfMap = message.getPayload();
Map<Object, Object> finalMap = new HashMap<Object, Object>();
for(Map<?, ?> map : listOfMap){
//you can use putAll if you don't care about duplicates
//finalMap.putAll(map);
// or a more complex algorithm to handle duplicates
for(Entry<?, ?> e : map.entrySet()){
if(finalMap.containsKey(e.getKey())){
//do something to handle situation when key is duplicate...
//you may want to check if both values are equals and skip this
//maybe throw an exception if values are different
//or keep a value
throw new Exception("Duplicate: " + e);
} else {
//key does not exists, put it
finalMap.put(e.getKey(), e.getValue());
}
}
}
return finalMap;
}
}
And then use this transformer in your flow. See the docs for details.
You have multiple ways of doing this one of which is flatten operator which merges 2 arrays into a single array. The other is to do it through the Dataweave Transform map operator and merging them as per your requirements.

Parsing Request Payload string

can anyone help me in parsing data from Request Payload string like following one:
7|0|5|https://www.bosscapital.com/app/Basic/|B8CC86B6E3BFEAF758DE5845F8EBEA08|com.optionfair.client.common.services.TradingService|getAssetDailyTicks|J|1|2|3|4|2|5|5|CB|U9mc4GQ|
Thanks & Regards
Ajay
You can call the Split() method on strings to split them at a certain character. Alternatively, you can use Regex.Split(value, "<pattern>"); for splitting, e.g. if you have multiple characters you want to split at. <pattern> is a string here, so you can provide more than one character (e.g. "\r\n" to find line breaks).
using System;
class Program {
static void Main() {
string s = "7|0|5|https://www.bosscapital.com/app/Basic/|B8CC86B6E3BFEAF758DE5845F8EBEA08|com.optionfair.client.common.services.TradingService|getAssetDailyTicks|J|1|2|3|4|2|5|5|CB|U9mc4GQ|";
// Split string at pipe character
string[] parts = s.Split('|');
// Process segments
foreach (string segment in parts) {
Console.WriteLine(segment);
// Use the segmented data...
}
}
}