Engine tries to write data to DB on read operations

Hi folks,

we observed an interesting/strange behavior of the engine. We were reading process variables (typed) from runtime or task service and received ConcurrentModificationException inside the ValuedValueField since our read operation was triggered by the HistoricEvent. This is due to the fact, that the command context is already closing (history events are fired on close), and the read operation trying to register a new CommandContextListener to flush the changed variables in the end.

Debugging further, we found out, that by doing so, Camunda Engine emulates the behavior of “Hibernate Managed Entities”, trying to flush changed entities…

I would like to start a larger discussion on that.

  1. It is not clear to me why this Hibernate Managed Entity for complex objects is required at all.

  2. If required - it could be switchable

  3. Even if required: there are ways to bypass the concurrent modification exception:

  • take a copy from the list before iteration
  • or detect the state of the command context (it is closing) and don’t add any listeners to the list then

As a workaround to bypass the ConcurrentModificationException we had to run our read operation in a NEW CommandContext. That worked for a moment, but failed in the next situation, as the deserialization/serialization marked the complex object as “dirty” (This might happen for example using SPIN with sets, causing reordering of the elements in JSON). The DBEntityManager detected the value change and decided to flush the new value to the database - resulting in OptimisticLockingException.

Again this can by worked around by manually flushing the DBEntityManager cache to prevent him from WRITING DATA ON READ-ONLY OPERATIONS, but this is very complicated and wierd…

Sorry for bold text, but we are really struggling with this.

Here is the original issue: Task enrichment fails if during the task update the data is changed · Issue #442 · holunda-io/camunda-bpm-taskpool · GitHub
If you are interested in the code, here is a PR of Lars for this: fix: avoid flushing accidental changes in inner command context when … by lbilger · Pull Request #443 · holunda-io/camunda-bpm-taskpool · GitHub

What do you think,

Cheers,

Simon

4 Likes

Hi Simon,

Good question, it’s age-old behavior in the process engine. We can’t remove it entirely based on backwards compatibility grounds and I also recall cases where people rely on this (and prefer it over explicit variable updates).

Yeah, that makes sense.

That also makes sense. For both cases we’ll gladly accept PRs. Probably being able to switch it off is cleaner and has more value.

Another idea for a workaround that could be less intrusive:

  1. Subclass CommandContext and initialize commandContextListeners as a CopyOnWriteArrayList
  2. Subclass CommandContextFactory so that it creates instances of your own command context
  3. Register the factory via the process engine configuration field commandContextFactory

That should achieve the “make a copy before iterating” behavior.

Cheers,
Thorben