This is more of a design level question than a specific problem I am having. Therefore I haven't published any specific code. I hope you can provide some views on it.
Imagine I have a jbpm process that uses my own custom fork node i.e. from the start node a number of child tokens are created and transitioned.
For the entire live of the process instance these tokens exist i.e. I'm not doing a join at any point.
The thing that concerns me is that I'm setting variables in the context instance and this context instance is shared between the tokens (threads). Furthermore each token is updating the same variable in the context instance. Now I am aware that the context instance can implement various levels of scope based on the token. However I want everything in the top level scope because I want to share data between the seperate tokens (threads). i.e. anything in the context instance gets copied to task node variables upon entering the node for every token.
Will the updating of the same variable in the same context instance cause a lost update problem. For example i'm worried about the following scenario.
1 Token 1 (thread one) gets the context instance and reads variable a
2 Token 2 (thread two) gets the context instance and reads variable a
3 Token 1 makes an update to variable a and persists it
4 Token 2 makes an update to variable a and persists it
At step 4 the update in step 3 is lost.
Will this be sorted out by hibernate if I get the right locking settings or do I need some sort of locking mechanism on my variable a? Apologies I'm not really that familiar with Hibernate by it seems having a process with multiple tokens (being signalled in multiple threads) and writing to the same variables in the top level scope (because I only want one shared copy), there might be classical concurrency issues?
Help is much appreciated
Your observations are correct, this is the classical concurrency issue and it is not an easy issue to solve. What you can at least do is declare each variable as a local one. Then they will be stored purely related to the token *first*... in a second step you can update the variable on a higher level after checking differences and you can always find all data back. (you also could do this via the logging mechanism since each update is logged)
Hibernate locking will not solve this, maybe hibernate versioning can in some way (but you'd have to know the initial version somewhere).
Normally we store as many data as possible in our own domain model and use processvariables for kind of fixed data like the businesskey.
I see what you mean kukeltje about keeping the changes local(related to the token) first, then adding the changes to the higher level. I'm not sure that would work though and this is my reasoning.
Eventhough the tokens have a different scope there is still only one context instance being shared between two threads. So
1. Thread one gets the context instance with variable A stored already at the root level.
2. Thread two gets the context instance with variable A stored already at the root level.
3. Thread one makes an update to his local var B and persists both his var B and var A.
4. Thread two makes an update to his local var C and persits both his var C and var A
Unfortunately the persistence of local var B by thread one (number 3) is lost when 4 is performed?
Is this not correct?
I know... the 'compare' has to go deeper... with 3 and 4 NOT storing it to the root level but e.g. using a special node which looks all data up, compares all three and maybe create new tasks (e.g. for the manager) BEFORE storing it at the root level. These kinds of 'decisions' have to be modelled into the process.
When you have threads instead of tasks it is more difficult, but not impossible... still most of the time it has to be in the process. Be it real workflow (e.g. assign to a manager to decide) or bpel like...(have some automatic rule to decide which 'wins')
Maybe the engine can help out a little by just giving a warning like 'original value has changed since reading'. This is already possible by using the logging from jBPM, since all updates are stored there. Sounds like some Business Process Isolation Level configuration ;-)