<flow name="calculateMinimum">
<java:invoke-static class="java.lang.Math" method="min(int,int)" >
<java:args>#[{
'arg0': 5,
'arg1' : "3"
}]
</java:args>
</java:invoke-static>
</flow>
Argument Transformation - Mule 4
Since Java Module version 1.1, this module transforms the arguments given to a Java invocation even if they don’t exactly match the type expected by the Java method. The Java module infers how to transform a parameter to what a method expects.
When Are Arguments Transformed?
For each specified parameter, the Java module checks whether its type matches the type expected by the method for that parameter or not. If it is not what the method expects, the Java Module transforms it to what is expected.
Simple Example of Argument Transformation
This is a simple example where one of the arguments is transformed.
The static method min
from the Math
class is called, but the class expects
to receive two int
parameters. The call is made with a Number and a String:
In this case arg1
would have been passed as a string, but it is transformed into an integer
before calling the Java method.
Pass a Custom POJO to a Module as a Map
In Mule 3 when working with custom POJOs, users explicitly declared in the DataWeave expression what type the data to transform. In Mule 4, the Java module automatically recognizes the expected type for an argument and tries to transform the data to the expected type. (POJO stands for plain old Java object.)
In the examples that follow, a Map parameter is transformed into a custom POJO by the Java module.
-
Define the
Car
class of the POJO:public class Car { private String doors; private String wheels; private String engine; public String getDoors() { return doors; } public String getWheels() { return wheels; } public String getEngine() { return engine; } }
-
Declare the
describeCar
static method in the class to receive an instance of the POJO:public class CarUtils { public static String describeCar(Car car) { return "This car has: " + car.getEngine() + ", " + car.getWheels() + ", " + car.getDoors(); } }
-
Invoke the static method in the Mule flow:
<flow name="describeCarFlow"> <java:invoke-static class="CarUtils" method="describeCar(Car)" > <java:args> #[{ 'car': { 'doors' : "Four doors", 'engine' : "120 Horsepower engine", 'wheels' : "17 Inch chromed rims" } }] </java:args> </java:invoke-static> </flow>
The Mule operation receives the
car
map whose key and values are mapped to aCar
class instance. This map is transformed into an instance before the invocation of the Java method. Without this improvement, the invocation would fail, stating that the arguments passed to the Java method did not match its signature.
Collections and Maps
The Java module checks that every element of the collection and every entry of the map honors the Java Generic declared by the method signature. If any element fails this check, the Java module creates the whole collection or map repopulates it with the transformed elements.
The Java method is called with another instance of the collection or map if a transformation is needed (not the same as the one passed in the Mule flow). This is particularly important if the method called is expected to add or remove elements in the collection or map, and the ability to reference this collection or map after the invocation is needed. |
Transform a List Example
The List
given to the operation is transformed and
a new List
with the transformed items is passed to the Java method.
The IntegerUtils
Java class declares the sumNumbers
static method:
public class IntegerUtils {
public static Integer sumNumbers(List<Integer> numbers) {
return numbers.stream().mapToInt(i -> i.intValue()).sum();
}
}
This Mule flow invokes the Java class:
<flow name="sumListOfNumbers">
<java:invoke-static class="IntegerUtils" method="sumNumbers(List)">
<java:args>
#[{
'numbers' : [1, "5", 4, "8", 3]
}]
</java:args>
</java:invoke-static>
</flow>
The numbers
list in the flow has two string objects ("5"
and "8"
), which the module transforms into integers.
Transform a Map Example
A map for the operation is transformed and a new map with the transformed keys and values is passed to the Java method.
This Java class declares the sumMapValues
static method:
public class MapUtils {
public static Integer sumMapValues(Map<String, Integer> map) {
return map.keySet().stream().mapToInt(i -> i.intValue()).sum();
}
}
This Mule flow invokes the MapUtils
Java class:
<flow name="sumValuesOnMap">
<java:invoke-static class="MapUtils" method="sumMapValues(Map)">
<java:args>
#[{
'map' :{
'books': "22",
'pencils': 33,
'pens': 12
}
}]
</java:args>
</java:invoke-static>
</flow>
This map contains values that do not comply with the generics imposed in the Java method. Because of this, a new instance with the transformed key and values is used to call the method.