Search code examples
mulemule4

Mule 4: Replace recurring node value in original payload


I have a recurring node/array in the JSON payload. I need to use value of the wonumber to call another service and the value from this service response has to be used to replace a code value on original message.

{
  "element1": "text1",
  "element2": "text2",
  "element3": "text3",
  "InvoiceItemDTO": [
    {
      "code": "",
      "itemNo": "1",
      "wonumber": 123
    },
    {
      "code": "",
      "itemNo": "2",
      "wonumber": 456
    }
  ]
}

The service response will give value for code field, which has to be copied back on original payload code value.

I have applied for each loop on the recurring node to make the call to service for each block in ItemDTO. But I am concerned about putting service response value field back on the original payload at the same index for which the service call was made.

If service call returns code value as abc1, def2 for above payload, then expected final payload is:

{
    "element1": "text1",
    "element2": "text2",
    "element3": "text3",
    "InvoiceItemDTO": [
        {
            "code": "abc1",
            "itemNo": "1",
            "wonumber": 123
        },
        {
            "code": "def2",
            "itemNo": "2",
            "wonumber": 456
        }
    ]
}

Any recommendations on how this can be achieved?


Solution

  • the for-each scope does not change the payload. If you want to retain some information gathered during execution of for-each you will need to store that data in a variable. As per the official doc

    Every execution of the For Each scope starts with the variables and values from the previous execution of the block. New variables or modifications to existing variables that take place when processing one element are visible during the processing of another element. These changes to variables continue to be available outside the For Each scope.

    For your use case you can do the following (Just a pseudo code)

    1. Collect all unique wonumber in an array and store it in a variable
      <set-variable variableName="wonumbers" value="#[payload.InvoiceItemDTO.wonumber distinctBy $]"/>
    2. Loop through this variable in the for-each scope
    3. After collecting the code for the wonumber store that as a map in a variable so that you can access it later.
      <foreach collection="#[vars.wonumbers]">
        <set-variable variableName="currentWonumber" value="#[payload]" />
        <do-your-thing.... />
        <set-variable variableName="wonumbersToCodeMapping" value="#[(vars.wonumbersToCodeMapping default {}) ++ (vars.currentWonumber): payload.code //however you are getting the code]"/>
      </foreach>
      
    4. Using the wonumbersToCodeMapping you can update the payload using update operator
    %dw 2.0
    output json
    ---
    payload update {
       case .InvoiceItemDTO -> 
          $ map ((item) -> item  update {
                case .code -> vars.wonumbersToCodeMapping[item.wonumber as String]
          })
    }