Personally I would not store complex objects (a simple collection would be the most complex one) in the bpm engine. If you have complex e.g. xml documents or whatever I would store them in a separate database and store a reference in the bpm engine
The following is still a question in my mind:
Why the objects are converted on each set, and reverted on each get? Is this really required?
Even if you do not have complex objects, if the number of the objects in the context and the number of access' to them increase, the performance will decrease. For example if you have 50 simple objects in your context, and 20 nodes in your process -that needs to read and update the context- then you have to 20 * 50 = 1000 convertion and 1000 revertion. Do we really have to go through this?
If these 20 nodes are states than you will want to persist the contents of the variables 20 times anyway. If you don't want to persist the content of these variables between the states, use transient variables.
Let me explain my case in detail:
We have processes that have many nodes, but only a couple of these nodes are wait states. For example, the process goes through 20 nodes and then in the 21. node, it needs to be persisted. And most of these nodes have access to the context.
We have already an application and I am trying to adapt it so that it is running with JBPM. In this application all the data that the process needs is kept in some type of collections (similar to hashtable). I mean using this type of object is a given.
So, to prevent the performance lost, I already used a transient variable to store the object just like you suggested, but when it comes to a wait state, I have to copy the transient variable, to make it persisted. But I cannot find a simple generic way of doing this, I am trying to find an entry point and automatically update the context just before it is persisted. I dont want to handle this in each process and in each case.
Do you have any suggestions?
the token.signal() method returns when all execution paths have reached a wait state. So if you want to intercept a wait state put your code directly after the outermost / initial token.signal() call.
But from what your describing maybe you don't need to do that at all. If you are executing 20 nodes in one call, all of these should be executed in a single transaction without a hibernate flush or commit to the database until the very end. In that case you might not need transient variables at all.
It's Meltem :)
Thank you for your response.
Since our processes are long running and complex processes, there may be several different outermost /initial token.signal() calls. For example in one process we assign an approval task to a user. And the user has several options to complete the task: approve / reject / send back... All of these resume the execution of the process (signals the process) with different transitions. So we should handle copying of the context in each. This will be repeated in some other steps of the process and this scenario will change for every process so each process needs special care. Each developer must be aware of this situation and implement accordingly.
What I want to do is isolate the developers from such a detail and provide a generic solution.
I want to use the objects by reference, but also persist them. It would be a great solution, if JBPM allowed this.
Maybe they consider to provide this improvement in the next releases. I think they should.
you would have to wrap execution in some kind of class of your own of course if you want to intercept all calls. In my current project - for various reasons - I had build a MDB that does all the signaling so I had a single point of entry. I even go further do encapsulate a lot of 'magic' from developers, but that won't help you much...
My other point was the neccessity of persisting in all nodes.
What is the scope of your transactions?
Does it span all 20 nodes?
If so, do you need to persist everytime, as it would only be flushed / commited once when returning from the last node?
If your nodes / actions are long running themself:
- do they run in seperate transactions?
- is persistence really a performance hit (if the action itself is longrunning already)?
Just my 2 cents..