Why can't I change Business Variables from two different threads of a Proces/Flow in a Paralell Multi-instantiation?

1
0
-1

Hi all

I am a newbie at Bonita 7.2.0, and have some questions.
I have a business Variable call InvestigationController(InvestigacionControlador in spanish), and I use this to save some Booleans values to know which tabs show, and which tabs show in read-only mode.
The problem is that I have an automatic task in the beginning of the processes to initialize this Boolean values to know where I am. And when I initialize this values in a Operation I get some errors in the logs warming me that the object has been changed, and the operation is being rolled back.
I think that the Business variable can't be changed simultaneously from different threads, but I thought that the bdm variables or business variables where independent in different flows or threads of Processes, that I could have different scope and values. But it seems that I am wrong.
I use this method because I have one unique form for all the tasks / states of the process, and I have to show in read-only mode depending on the role of the user or in the task that is the process. I was thinking in using a BDM variable called controller to store some Booleans that could help me to know which fields of the form show in read-only mode and which in editable mode.
I think I have to use many independent simple variables and forget the idea of using a complex data with a Business variable using a BDM (Business Data Model). If some know how to do it I will appreciate it help. It seems to be a concurrence problem.

Is there any way of make a copy of the data or values of the BDM variable, but in a different instance or variable for each thread of the process?
All the variables that I want different instance I would have to put it in the vector of instantiation? And iterate with a variable on it.

LOG ERROR:

GRAVE: THREAD_ID=946 | HOSTNAME=SSABONDS0000 | TENANT_ID=1 | The work [ExecuteFlowNodeWork: processInstanceId:49048, flowNodeInstanceId: 980234] failed. The failure will be handled.
2016-08-18 17:12:56.145 +0100 org.bonitasoft.engine.execution.work.FailureHandlingBonitaWork org.bonitasoft.engine.log.technical.TechnicalLoggerSLF4JImpl log
GRAVE: THREAD_ID=946 | HOSTNAME=SSABONDS0000 | TENANT_ID=1 | org.bonitasoft.engine.transaction.STransactionCommitException : "PROCESS_DEFINITION_ID=6333068206714559759 | PROCESS_NAME=Investigacion | PROCESS_VERSION=1.4 | PROCESS_INSTANCE_ID=49048 | ROOT_PROCESS_INSTANCE_ID=49046 | FLOW_NODE_DEFINITION_ID=5111074264105123943 | FLOW_NODE_INSTANCE_ID=980234 | FLOW_NODE_NAME=Inicializa Controlador Investigación | bitronix.tm.internal.BitronixRollbackException: RuntimeException thrown during beforeCompletion cycle caused transaction rollback"
org.bonitasoft.engine.transaction.STransactionCommitException: PROCESS_DEFINITION_ID=6333068206714559759 | PROCESS_NAME=Investigacion | PROCESS_VERSION=1.4 | PROCESS_INSTANCE_ID=49048 | ROOT_PROCESS_INSTANCE_ID=49046 | FLOW_NODE_DEFINITION_ID=5111074264105123943 | FLOW_NODE_INSTANCE_ID=980234 | FLOW_NODE_NAME=Inicializa Controlador Investigación | bitronix.tm.internal.BitronixRollbackException: RuntimeException thrown during beforeCompletion cycle caused transaction rollback
        at org.bonitasoft.engine.transaction.JTATransactionServiceImpl.commit(JTATransactionServiceImpl.java:225)
        at org.bonitasoft.engine.transaction.JTATransactionServiceImpl.complete(JTATransactionServiceImpl.java:194)
        at org.bonitasoft.engine.transaction.JTATransactionServiceImpl.executeInTransaction(JTATransactionServiceImpl.java:322)
        at org.bonitasoft.engine.execution.work.TxBonitaWork.work(TxBonitaWork.java:53)
        at org.bonitasoft.engine.execution.work.LockProcessInstanceWork.work(LockProcessInstanceWork.java:79)
        at org.bonitasoft.engine.execution.work.failurewrapping.TxInHandleFailureWrappingWork.work(TxInHandleFailureWrappingWork.java:42)
        at org.bonitasoft.engine.execution.work.failurewrapping.TxInHandleFailureWrappingWork.work(TxInHandleFailureWrappingWork.java:42)
        at org.bonitasoft.engine.execution.work.failurewrapping.TxInHandleFailureWrappingWork.work(TxInHandleFailureWrappingWork.java:42)
        at org.bonitasoft.engine.execution.work.FailureHandlingBonitaWork.work(FailureHandlingBonitaWork.java:66)
        at org.bonitasoft.engine.work.BonitaWork.run(BonitaWork.java:56)
        at org.bonitasoft.engine.work.SequenceRunnableExecutor.innerRun(SequenceRunnableExecutor.java:47)
        at org.bonitasoft.engine.work.BonitaRunnable.run(BonitaRunnable.java:35)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:745)
Caused by: bitronix.tm.internal.BitronixRollbackException: RuntimeException thrown during beforeCompletion cycle caused transaction rollback
        at bitronix.tm.BitronixTransaction.commit(BitronixTransaction.java:241)
        at bitronix.tm.BitronixTransactionManager.commit(BitronixTransactionManager.java:143)
        at org.bonitasoft.engine.transaction.JTATransactionServiceImpl.commit(JTATransactionServiceImpl.java:223)
        ... 14 more
Caused by: javax.persistence.OptimisticLockException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.company.model.InvestigacionControlador#80]
        at org.hibernate.ejb.AbstractEntityManagerImpl.wrapStaleStateException(AbstractEntityManagerImpl.java:1413)
        at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1329)
        at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1310)
        at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1316)
        at org.hibernate.ejb.AbstractEntityManagerImpl$CallbackExceptionMapperImpl.mapManagedFlushFailure(AbstractEntityManagerImpl.java:1510)
        at org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorNonTrackingImpl.beforeCompletion(SynchronizationCallbackCoordinatorNonTrackingImpl.java:110)
        at org.hibernate.engine.transaction.synchronization.internal.RegisteredSynchronization.beforeCompletion(RegisteredSynchronization.java:53)
        at bitronix.tm.BitronixTransaction.fireBeforeCompletionEvent(BitronixTransaction.java:532)
        at bitronix.tm.BitronixTransaction.commit(BitronixTransaction.java:235)
        ... 16 more
Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.company.model.InvestigacionControlador#80]
        at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:2521)
        at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3240)
        at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3138)
        at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3468)
        at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:140)
        at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:395)
        at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:387)
        at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:304)
        at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:349)
        at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
        at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1159)
        at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:404)
        at org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorNonTrackingImpl.beforeCompletion(SynchronizationCallbackCoordinatorNonTrackingImpl.java:105)
        ... 19 more

Thank you very much.

Any assistance would be greatly appreciated.

Kind regards,
Héctor

2 answers

1
+1
-1
This one is the BEST answer!

This is to be expected...this is the good old "seat reservation" issue which every software engineer will have learnt at college.

Think of it this way:

2 travel agents serving 1 passenger each
1 plane
1 seat left

Both agents are running the booking process at the same time.

travel agent 1 books the seat so passenger one gets it, but at the same time (or milliseconds after) travel agent 2 books the seat for passenger 2 gets it and the seat is now lost to passenger one...

This is simply NOT allowed.

The problem is that I have an automatic task in the beginning of the processes to initialize this Boolean values to know where I am. And when I initialize this values in a Operation I get some errors in the logs warming me that the object has been changed, and the operation is being rolled back.

When you say automatic task are you talking about a Service Step?

I think that the Business variable can't be changed simultaneously from different threads, but I thought that the bdm variables or business variables where independent in different flows or threads of Processes, that I could have different scope and values. But it seems that I am wrong.

BDM variables are only independent if you are creating a instance of the BDM which can be locked to the case. But you have seen the problem...it doesn't work that way and changing a BDM locks it.

I use this method because I have one unique form for all the tasks / states of the process, and I have to show in read-only mode depending on the role of the user or in the task that is the process. I was thinking in using a BDM variable called controller to store some Booleans that could help me to know which fields of the form show in read-only mode and which in editable mode.

In this case what you need is a process to Create and Change the BDM for each Role and then in your process Read the appropriate BDM (by role) and set the fields accordingly,

So what you have is

Global process that reads BDM by role and sets fields in forms
Role process that sets the BDM for a role

2 roles = 2 BDM
5 roles = 5 BDM
10 roles = 10 BDM

regards
Seán

PS: If this reply answers your question, please mark as resolved.

Comments

Submitted by hectorta on Mon, 08/22/2016 - 09:52

Thank you very much this is what I need a different Bdm for each role, to control it.
My error was thinking that a BDM in each thread was different instance in Bonita, and in Data Base, I didn't know that it was the same instance and the same row in the Data Base, and the same "ID" obviously you can't modify it at the same time in different "processes".
For my, it was a “don't written rule”, that I have to learn, that the BDM variable was the same instance in the different threads of the flow.

Thank you very much for your help.

1
0
-1

Hi Hector,

If I understand correctly, you have one automatic tasks that update a bdm object through operations, is that correct? If so, I think that the update should work just fine. Are you doing something else in parallel? Do you want to share your process so maybe I can take a look?

Cheers

Notifications