DataWeave language is the primary expression language in Mule 4, and is encourage to use DataWeave whenever possible. However for practicality or for whatever reason, there is always some scenario that one wish to use other general purpose programming language, such as Groovy,Python to build some logic to achieve the same result, probably in elegant/faster/easier/better understandable way. So, it is always good that we have options.
In this example will explore Groovy Scripting in Mule 4.
Firstly, drag Scripting/Execute step into flow:
In Execute step, Code section put “${file::MyScript.groovy}”.
This is reference to groovy file named ‘MyScript.groovy’ in mule project. Reference to file instead of coding direct inside Execute step, enable us to develop, debug the groovy script externally using your choice of favorite editor (e.g. IntelliJ IDEA). This save time and improve productivity, because to test in mule project, will need deploy the whole mule flow every time some code change.
Script file should put at path ‘src/main/resources’. Note that should not physical go to file system to place the script, in stead should use import method.
To import groovy file, right click, Import..
Choose General,File System.
Browse to directory that contain script, here example put at folder ‘C:\AnyScript’. Tick to select scripts want to import, then Finish.
If the script required import statement reference to other external jars. Go to Java Build Path, Libraries, Add External JARs, then choose external jars required. Example:
import org.apache.commons.io.IOUtils;
Besides, need edit file “mule-artifact.json” to add resource want to export.
Reference: https://docs.mulesoft.com/mule-runtime/4.1/how-to-export-resources
{
"minMuleVersion": "4.1.4",
"classLoaderModelLoaderDescriptor": {
"id": "mule",
"attributes": {
"exportedPackages": [
"org.apache.commons.io"
]
}
}
}
Also need to add dependency in file “pom.xml” under dependencies. Example: added “common-io” version 2.6.
<dependencies>
<dependency>
<groupId>org.mule.connectors</groupId>
<artifactId>mule-http-connector</artifactId>
<version>1.3.2</version>
<classifier>mule-plugin</classifier>
</dependency>
<dependency>
<groupId>org.mule.connectors</groupId>
<artifactId>mule-sockets-connector</artifactId>
<version>1.1.2</version>
<classifier>mule-plugin</classifier>
</dependency>
<dependency>
<groupId>org.mule.modules</groupId>
<artifactId>mule-scripting-module</artifactId>
<version>1.1.3</version>
<classifier>mule-plugin</classifier>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
Next we can deal with the development of groovy script.
In groovy script, if want to directly use mule payload as string, will hit error, due to payload is of type inputStream. Need to convert inputStream to string first.
Below are 2 ways tested able to convert inputStream to string:
option 1: Using plain Java:
static String StreamToString_Java(java.io.InputStream is) {
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}
option 2: Using IOUtils.copy() function. Need import org.apache.commons.io.IOUtils in groovy script.
static String StreamToString_IOUtils(java.io.InputStream is) {
StringWriter writer = new StringWriter();
IOUtils.copy(is, writer, "UTF-8");
return writer.toString();
}
Full groovy script:
BuildOutput() function contain necessary code required.
TestRun() is for local development and test run to see the output.
In below groovy script is to transform nested json to flat json.
import groovy.json.*
import org.apache.commons.io.IOUtils;
static String StreamToString_Java(java.io.InputStream is) {
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}
static String StreamToString_IOUtils(java.io.InputStream is) {
StringWriter writer = new StringWriter();
IOUtils.copy(is, writer, "UTF-8");
return writer.toString();
}
//TestRun()
BuildOutput(StreamToString_IOUtils(payload))
def String TestRun(){
input_file_path = "C:\\AnyData\\orders_nested.txt";
output_file_path = "C:\\AnyData\\orders_nested_output.txt";
def input = new File(input_file_path).getText('UTF-8')
def output = BuildOutput(input)
println(output)
File file = new File(output_file_path)
file.write output
}
def String BuildOutput(String input) {
def Source = new JsonSlurper().parseText(input)
def writer = new StringWriter()
def builder = new StreamingJsonBuilder(writer)
builder {
Source.Orders.each { ord ->
ord.Items.each{ itm ->
itm.Variants.each{ vrt ->
row {
OrderID(ord.OrderID)
Customer(ord.Customer)
Country(ord.Country)
ProductID(itm.ProductID)
UnitPrice(itm.UnitPrice)
Color(vrt.Color)
Quantity(vrt.Quantity)
}
}
}
}
}
return JsonOutput.prettyPrint(writer.toString())
}
Input nested json:
{
"Orders": [{
"OrderID": 2501,
"Customer": "Alex",
"Country": "USA",
"Items": [{
"ProductID": "P05",
"UnitPrice": 50,
"Quantity": 1,
"Variants": [{
"Color": "Blue",
"Quantity": 1
}
]
}
]
}, {
"OrderID": 2502,
"Customer": "Bob",
"Country": "UK",
"Items": [{
"ProductID": "P05",
"UnitPrice": 50,
"Quantity": 5,
"Variants": [{
"Color": "Blue",
"Quantity": 2
}, {
"Color": "Red",
"Quantity": 3
}
]
}, {
"ProductID": "P06",
"UnitPrice": 80,
"Quantity": 1,
"Variants": [{
"Color": "Yellow",
"Quantity": 1
}
]
}
]
}, {
"OrderID": 2503,
"Customer": "Peter",
"Country": "UK",
"Items": [{
"ProductID": "P07",
"UnitPrice": 120,
"Quantity": 10,
"Variants": [{
"Color": "Green",
"Quantity": 4
}, {
"Color": "Yellow",
"Quantity": 6
}
]
}
]
}
]
}
Output flat json:
{
"row": {
"OrderID": 2501,
"Customer": "Alex",
"Country": "USA",
"ProductID": "P05",
"UnitPrice": 50,
"Color": "Blue",
"Quantity": 1
},
"row": {
"OrderID": 2502,
"Customer": "Bob",
"Country": "UK",
"ProductID": "P05",
"UnitPrice": 50,
"Color": "Blue",
"Quantity": 2
},
"row": {
"OrderID": 2502,
"Customer": "Bob",
"Country": "UK",
"ProductID": "P05",
"UnitPrice": 50,
"Color": "Red",
"Quantity": 3
},
"row": {
"OrderID": 2502,
"Customer": "Bob",
"Country": "UK",
"ProductID": "P06",
"UnitPrice": 80,
"Color": "Yellow",
"Quantity": 1
},
"row": {
"OrderID": 2503,
"Customer": "Peter",
"Country": "UK",
"ProductID": "P07",
"UnitPrice": 120,
"Color": "Green",
"Quantity": 4
},
"row": {
"OrderID": 2503,
"Customer": "Peter",
"Country": "UK",
"ProductID": "P07",
"UnitPrice": 120,
"Color": "Yellow",
"Quantity": 6
}
}
🙂