Mule 4 - Accumulating Values in a For Each

Mule 4 - Accumulating Values in a For Each

This is a written post on the topic covered in my YouTube video:

This post reviews how to accumulate a value into an array within a for-each loop. I'm going to cover how to do this in Mule 4, where we don't have access to MEL. In Mule 3, the solution to this problem is pretty well understood. You use the Expression component:

Screen-Shot-2018-08-18-at-22.10.05

In "Init acc" we set flowVars.acc to an empty array, []. Then, in the "Add result to acc" Expression component within the For Each scope, we call the List.add(E e) method (documentation here). Therefore, for every iteration through the For Each, the Expression component modifies the object that flowVars.acc points to directly, adding a value to the List. The expression component would contain the following code (assuming callMockService returns {"value": 1}):

flowVars.acc.add(flowVars.result.value)

This is perfectly fine in Mule 3, but remember, we don't have MEL at our disposal in Mule 4, so how do we accomplish this?

You have a couple options, you could use the Java module's Invoke or Invoke Static components to accomplish this, but honestly, I think that's overkill. Your other option is to use DataWeave. But we hit another roadblock here. If you remember from my post on DataWeave for Java progammers, you can't modify data structures using DataWeave. So again, how do we accomplish this?

If you're familiar with functional programming, you should know that this problem is also pretty well understood: we reassign the variable with the new value we'd like to update it to. This is actually simplier than it sounds. For example in Java we could do the following to increment a variable:

number++;

But we could also do it this way:

number = number + 1

They accomplish the exact same thing. We're going to use that same pattern to accumulate values into the acc array.

This is what that looks like in Mule 4:

Screen-Shot-2018-08-18-at-18.59.20

Not really all that different from what we have above, but you'll notice I replaced the expression component with a Transform Message component. Let's look at the transformer code itself to see what's going on.

Screen-Shot-2018-08-18-at-19.04.20

Please ignore the alarming red exclamation point, that's just an Anypoint Studio issue; it has nothing to do with improper syntax.

Let's walk through exactly what this code is doing. We'll assume we're going through our first iteration, so vars.acc is currently []. We call the mock service and get back {"value": 1}. Then the Transform Message component is taking vars.acc, currently [], and using the + function to push vars.result.value onto the end of that array (remember though, we can't modify existing data structures, so we're actually creating a brand new array here). It's then assigning the output of the script to the variable vars.acc, effectively reassigning it. Now vars.acc is set to [1], and the process continutes until the For Each loop is finished iterating.

Ultimately, the mindset behind accumulating values into the array is very different from Mule 3 and Mule 4. This is because MEL still allowed us to think about code in an imperitive fashion, but with Mule 4, where DataWeave completely replaces MEL, we need to think in a more functional fashion.