Storing & accessing nested structures in the Camunda context

The data that we’re currently storing in the Camunda context is composed of nested java.util.Maps. Here’s how we correlate messages to the engine, along with passing the context:

Map<String, Object> context = <construct map>;
var builder = processEngine.getRuntimeService()
    .createMessageCorrelation(MESSAGE_NAME)
    .processInstanceVariablesEqual(CORRELATIONS)
    .setVariables(context);

The issue that we face at the moment is how to update only parts of the context. Lets say in a running process we have the following context:

vendingMachineId: "123",
inventory: [
    "coke": ["quantity": 1, price: "10"],
    "pepsi": ["quantity": 2, price: "5"]
]

The [:] syntax means a map. From what we read, the inventory would be stored as a LOB in the database. Is there a way to update only a part of this LOB? For example, to decrease the quantity of pepsi to 1, by correlating a message with the variables inventory: [pepsi: ["quantity": 1]]. Effectively performing a merge instead of a replace. Is there a way to customise how the context is updated?

One solution 1), or a workaround, that we found is to flatten the maps, so that the context looks like this:

vendingMachineId: "123",
inventory.coke.quantity: "1",
inventory.coke.price: "10",
inventory.pepsi.quantity: "2",
inventory.pepsi.price: "5"

In this case we can directly replace only inventory.pepsi.quantity. However, this brings the following disadvantages:

  • more load for the database for each running process, as each variable is a separate row
  • clumsier usage of the variables in the BPMN, as we can no longer directly use inventory.pepsi.price but have to call execution.getVariable('inventory.pepsi.price').

As an improvement we can introduce a custom function, lets say c, and call it in expressions - ${c('inventory').pepsi.price > 10. This way we can maintain a flattened context, as in solution 1), but at least make the bpmn usage slightly easier. Of course the desired expression would simply be ${inventory.pepsi.price}.

Kind regards,
Milan

1 Like

Being able to update parts of a map in a context would be helpful. I’m also interested to see if that’s possible and how to implement it (apart from having to perform manual correlation and update of the context).