The data that we’re currently storing in the Camunda context is composed of nested java.util.Map
s. 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 callexecution.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