How to Accumulate and Modify Values into Variable Using Mule 4 and DataWeave 2? - InterWorks

How to Accumulate and Modify Values into Variable Using Mule 4 and DataWeave 2?

Very often when we are working with values and variables, we need to store some value in a variable and modify that value when needed. If you are working with MuleSoft, you have probably noticed that after the initial assignment of a variable, we cannot change that value in DataWeave transformation.

While working with variables and DataWeave, we have come to the solution of the previously mentioned problem. Therefore, in this blog post, we will explain how to store, modify, and use a variable value at any stage of the DataWeave script into a single transform message using the accumulator pattern in DataWeave 2 using Java HashMap class.

To use the java HashMap class we need to import the java module (Check Figure 1).

Figure 1: Import Java Module

One of the core parts of the accumulator pattern is to initiate a variable that we are going to use as an accumulator. In our case, we are going to use “accumulatorVar” that contains four keys with the initial values of different data types (Check Figure 2).

Figure 2: Accumulator Variable

Figure 3: Accumulator Flow

After the initialization of the accumulator variable “accumulatorVar” we can use the below functions to accumulate the values.

fun accumulateValues (varName, keyName, add) = 
using (addValue = 
     Java::invoke(			                   //invoke java.util.HashMap
	    'java.util.HashMap',
    'put(Object,Object)',	                         //method used to add values
	     varName,                               //variable for accumulating values
		  {								
		     arg0: keyName,                                          // key name
		     arg1: add( Java::invoke(              //add to accumulator variable
                    'java.util.HashMap',
                    'get(Object)',                         //method used to get value
                     varName,
                     {arg0: keyName}
                                )
          			         )
				           }
			            )
		             )
 Java::invoke('java.util.HashMap', 'get(Object)', varName, {arg0: keyName})  //return

The function “accumulateValues” is using Java::invoke DataWeave function to invoke put(Key, Value) method from java.util.HashMap class. To update the value from the accumulator variable first we need to get the current value using get(Key) method and after we get the value from the accumulator variable we add a new value and store the updated value in the same variable.

Let’s see how this function works on a simple mathematical example:

[1,2,3] map (value,index) -> {
	("Iteration " ++ index + 1) : accumulateValues (
vars.accumulatorVar, 'intKeyName', (accVar) -> accVar + value
       )
    }

We pass three parameters to the function “accumulateValues”:

1. Accumulator variable (“accumulatorVar”)
2. Name of the key where we want to accumulate value (“intKeyName”)
3. Lambda function to sum the values (accVar) -> accVar + value

In the DataWeave script above, the key “intKeyName” of the variable “accumulatorVar” starts with an initial value of 0. We iterate through the list three times using the map operator and “value” has the value from the current iteration. In each iteration, the key “intKeyName” from “accumulatorVar” variable is reassigned with a new value which is the sum from old value plus the current value ((accVar) -> accVar + value) but we can also use all other mathematical operation.

Result:

[
    {
        "Iteration 1": 1
    },
    {
        "Iteration 2": 3
    },
    {
        "Iteration 3": 6
    }
]

We can confirm that after the execution of the transform message the Logger component will print value 6 for vars.accumulatorVar.intKeyName variable.

Additionally, we will explore the example of accumulating String values in different stages of the DataWeave script and the usage of different String operations like concatenate and replace.

[
  {
   "str1": accumulateValues (
             vars.accumulatorVar, 'strKeyName', (accVar) -> accVar ++ "Mule"
                 )
	   },
  {
    "list": [{
		"str2": accumulateValues (
vars.accumulatorVar, 'strKeyName', (accVar) -> accVar ++ "Soft"
    ),
		"num1": 1
		}]
	   },
  {
    "str3": accumulateValues (
      vars.accumulatorVar, 'strKeyName', (accVar) -> accVar replace "Soft" with " 4"
              )
	   }
]

In the dataweave script above, the key “strKeyName” of the variable “accumulatorVar” starts with the initial value “” (empty String).

In the first invocation of “accumulateValues” function we concatenate “Mule” with the initial value “” (empty String) and the value of “strKeyName” is reassigned with new value “Mule”.

In the second invocation, we concatenate the old value “Mule” with the new value “Soft” and the value of “strKeyName” is reassigned with the new value “MuleSoft”.

In the last invocation, the String “Soft” from the old value “MuleSoft” is replaced with “4” and reassigned the value to “Mule 4”.

Result:

[
  {
    "str1": "Mule"
  },
  {
    "list": [
      {
        "str2": "MuleSoft",
        "num1": 1
      }
    ]
  },
  {
    "str3": "Mule 4"
  }
]

We can confirm that after the execution of the transform message the Logger component will print the value “Mule 4” for vars.accumulatorVar.strKeyName variable.

Additionally, we will explore an example of accumulating Objects and see how we can accumulate the current value and assign another value to the key where we invoke the “accumulateValues” function.

To achieve this, we need to update the “accumulateValues” function:

1. Add new parameter “return

2. Replace the last line of “accumulateValues” function with “return

[
	{
		"obj1": accumulateValues (
	vars.accumulatorVar, 'listKeyName', (accVar) -> accVar + {"key1": "value1"}, 
    {"key1": upper("value1")}
   		 			)
	},
	{
		"list1": [{
				"obj2": accumulateValues (
vars.accumulatorVar, 'listKeyName', (accVar) -> accVar + {"key2": "value2"}, {}
    				)
			}
		]
	},
	{
		"listAllObj": Java::invoke(
'java.util.HashMap', 'get(Object)', vars.accumulatorVar,{arg0: 'listKeyName'}
)
	}
]

In the DataWeave script above we are invoking “accumulateValues” function using “accumulatorVar” variable and key “listKeyName” with initial value [] (empty Array). We invoke the function in different stages of the DataWeave script and add Objects into the Array. The result of the accumulation is used only at the key “listAllObj”.

Result:

[
    {
        "obj1": {
            "key1": "VALUE1"
        }
    },
    {
        "list1": [
            {
                "obj2": {}
            }
        ]
    },
    {
        "listAllObj": [
            {
                "key1": "value1"
            },
            {
                "key2": "value2"
            }
        ]
    }
]

To sum up, having the ability to store values in a variable and modify that value when you most need it is really important. Not only it reduces the developer’s time, but it also enhances the developer’s skills. In our blog post, you were able to see the function that accumulates values in a variable and how to accumulate all data types in different stages of the DataWeave script.

If you need more information about our solution or want to discuss it, feel free to contact us. Additionally, we have the same solution in Mule 3, so if you are interested about it, you can contact us as well.

Goran Petrovski
Goran Petrovski