cancel
Showing results for 
Search instead for 
Did you mean: 

Usage of more than one Activiti Engines on one database

wegalt
Champ in-the-making
Champ in-the-making
Hi,
I want to use the Activiti Explorer, the Activiti-Rest web app and an Activiti-engine embedded in a native application on the same database (activiti 5.11). It should e.g. possible to start a BPM process within a native java application via the activiti engine itself (embedded activiti engine), fill in some user data of a usertask with the activiti-explorer and a third application, which has no access to the Activiti-database, uses the Activiti-Rest application, also deployed as an own web app on its own webserver, to send a message to a ReceiveTask of that proccess.
It is mentioned in the book Activit in Action section 8.1.2, that Activiti is designed to run multiple Activiti engines on the same database (there are running two Activiti Engines in one tomcat server). 
Do I understand the documentation correctly that everything should work because of the activiti job executor and the database row locks?

If this would work, what happens if a process which waits for example for a user-request and a receive-task (because of a parallel gateway) and both of the requests are completed by different applications at same time? The user-request gets an answer from the Activiti Explorer and the Receive task is answered by an incoming rest-call or maybe by an embedded Activiti Engine via an Activiti-Api call?

What kind of problems do I have to be preparing for, also? One thing I know is that I have to deploy the necessary JARs to all the applications.

5 REPLIES 5

jbarrez
Star Contributor
Star Contributor
<code>
Do I understand the documentation correctly that everything should work because of the activiti job executor and the database row locks?
</code>

Correct. Activiti is designed to scale horizontally in a stateless way.

<code>
If this would work, what happens if a process which waits for example for a user-request and a receive-task (because of a parallel gateway) and both of the requests are completed by different applications at same time? The user-request gets an answer from the Activiti Explorer and the Receive task is answered by an incoming rest-call or maybe by an embedded Activiti Engine via an Activiti-Api call?
</code>

One of them will get an ActivitiOptimistLockingException. You can catch this exception and act accordingly (eg display something like 'someone else was faster then you' 😉 ).

<code>
What kind of problems do I have to be preparing for, also? One thing I know is that I have to deploy the necessary JARs to all the applications.
</code>

Yes you would need to have the Activiti libs (jars) wherever you want to interact with the engine through Java

wegalt
Champ in-the-making
Champ in-the-making
Thanks for your answer.

I have recreated a scenario with multiple processes (two Java Progam on an Activiti database) once and am unfortunately met with an unpleasant behavior.    

One of them will get an ActivitiOptimistLockingException. You can catch this exception and act accordingly (eg display something like 'someone else was faster then you' ;-) ).
I think the error message that two Java processes running on the same BPM process comes too late. 
(Error log of the two scenarios is in the appended file  Exceptions.txt seperated by "–Sql Exception if I use two native java programms–" and "–ActivitiOptimistLockingException in the Activiti Explorer–"

I use the following BPM Process:
  1. Start - Enter the Variables
  2. User Task1 - Entering variables e.g.<code>taskService.complete(task.getId(), variableMap);</code>
  3. Service task - compiling the variables from the start and the user Task1
  4. User Task 2 - Display the combined variables from the service task
First I put a breakpoint in the service task.
  1. Set a breakpoint in the service task
  2. Start A simple Java program that starts the process instance variables with corresponding
  3. Program A: Search for the user Task1 and komplementiere it with the corresponding variables
  4. Program A: stops at breakpoint set)
  5. Create simple Java program B with its own Enginge process that starts the process instance variables with corresponding
  6. Program B: Search for the user task1 and komplementiere him with the other variables
  7. Program B: Let it run over the breakpoint
  8. Program B: comes to user-task2 without problems
  9. Program A: continue to run
  10. Program A: terminates the service task and throws exceptions
Program A Program B has overhauled and both have eg emails sent out, although it may only have one complementing the user Task1. Program B may ever enter the service task if A has previously completed the user task?
At first I thought that the error occurs because I am using two independent Java programs with a Acitivi DB. But I had the same behavior (same impact, but other error messages) also in the Activiti Explorer. But there are used only two threads and no two processes with independent activiti engines.     

I use the same user twice "kermit" with two different browsers with the Activiti Explorer test
  1. A browser starts the process
  2. A browser user fills Task1 (with value 1) and completes it.
  3. A browser (thread A) remains at the break point, the service task are
  4. Browser B fills the same user Task1 (with value 2) and completes it.
  5. Browser B (Thread B) remains at the break point, the service task are, but I let him continue to run
  6. Browser B shows the values ​​from the user to Task2
  7. A browser throws error when I run the thread further
The System.out.println logging during the service task of the browser is outdated thread A thread B. You can see the first user sets Value = 1 and the second Value =2. The second user wins :
  1. StartServiceTask 2013-06-13 00:43:38.069; Value: 1; execution.getProcessInstanceId(): 14969
  2. IntheMiddleofServiceTask 2013-06-13 00:43:48.149; Value: 1; execution.getProcessInstanceId(): 14969
  3. StartServiceTask 2013-06-13 00:44:29.282; Value: 2; execution.getProcessInstanceId(): 14969
  4. IntheMiddleofServiceTask 2013-06-13 00:44:36.864; Value: 2; execution.getProcessInstanceId(): 14969
  5. EndServiceTask 2013-06-13 00:44:45.088; Value: 2; execution.getProcessInstanceId(): 14969
  6. EndServiceTask 2013-06-13 00:48:18.412; Value: 1; execution.getProcessInstanceId(): 14969
I always use the default settings. Standard DB jdbc:h2:tcp://localhost/activiti;DB_CLOSE_DELAY=1000 For native clients and the Activiti Explorer scenario the \ activiti-5.11src \ project defaults.

Can it be that two threads / processes work the same process instance and the last thread enters the wait-element throwa an exception. Actions such as sending emails can't be undone? What I need is a exception immediately after the second thread tries to finish the user-task1 Smiley Happy

I guess that if I'd used instead of the user tasks  rereceive tasks, I have the same problem?     

Does anyone have an idea what I'm doing wrong, or is that the normal behavior?

trademak
Star Contributor
Star Contributor
As far as I understand, you are doing anything wrong. What would be the expected behavior for would? When you are performing actions on the same process instance from multiple servers / threads, one of them will lose due to the optimistic locking implementation in the Activiti Engine. The transaction will be rollbacked as expected, but logic you have executed in service tasks or mail tasks that are not using the same transaction can't be undone. I think that's normal behavior.

Best regards,

wegalt
Champ in-the-making
Champ in-the-making
<blockquote>What would be the expected behavior for would?</blockquote>
I would expect that if two supply processes have a message for one BPM process instance (see attachment Simple_process) and one after the other forward its message to the BPM process instance, only one message should reach the send mail service task. The other process should get an <code>ActivitiOptimisticLockingException</code> within the Receive task.                                  


But in fact, both messages reach the send mail service task and get processed. The first process which reached the end commits the instance. The second process gets a  <code>ActivitiOptimisticLockingException</code> as soon as he reaches the end event. In some way, if I set the service task <code>async=true</code> it’s possible to get my expected behavior, but then the message sender loses the execution control of the following tasks.                

<blockquote>As far as I understand, you are doing anything wrong</blockquote>     
  1. Where do you think is my missunderstanding. Should only one message sender exist for a particular receive task to prevent the duplicated service task execution?
  2.             
                   
  3. Of course, the rollback of any previously sent message can’t withdraw. Am I correct that I have no chance to compensate the mistake within the bpm process (maybe through sending a third message), because the <code>ActivitiOptimisticLockingException</code> occurs not within the process definition but rather on commit. I have no chance to catch the exception within the process. Secondly, the process instance is already committed when the exception occurs. If you know a way to handle the exception within the bpm process I would be glad to get to know.


  4. In this example bpm process with a receive task I get a <code>ActivitiOptimisticLockingException</code>. The same exception occurs if I replace the receive task by a user task. However, I am surprised that I received a <code>PersistenceException</code><code>
  5. 12.06.2013 20:04:40 org.activiti.engine.impl.interceptor.CommandContext close
    SCHWERWIEGEND: Error while closing command context
    org.apache.ibatis.exceptions.PersistenceException:
    ### Error updating database.  Cause: org.h2.jdbc.JdbcSQLException: Referentielle Integrität verletzt: "ACT_FK_VAR_EXE: PUBLIC.ACT_RU_VARIABLE FOREIGN KEY(EXECUTION_ID_) REFERENCES PUBLIC.ACT_RU_EXECUTION(ID_) ('12803')"
    Referential integrity constraint violation: "ACT_FK_VAR_EXE: PUBLIC.ACT_RU_VARIABLE FOREIGN KEY(EXECUTION_ID_) REFERENCES PUBLIC.ACT_RU_EXECUTION(ID_) ('12803')"; SQL statement:</code> in the case of the previous post. The process from the previous post set internal process variables and task additional. Can I assume that I simply should catch both exceptions outside the bpm process? The changes where the PersistenceException occurred will be completely rolled back also?
           

Thanks!

mmaker1234
Champ in-the-making
Champ in-the-making
Hello,

First of all I think that you mixed the problems related to the number of engines with the problems related to simultaneous external impact on the process instance:<i>"… I want to use the Activiti Explorer, the Activiti-Rest web app and an Activiti-engine embedded in a native application on the same database

what happens if a process which waits for example for a user-request and a receive-task (because of a parallel gateway) and both of the requests are completed by different applications at same time?"
</i>
Let me note that a simultaneous impact on the process instance could happen even with a single engine instance. For example there could be a user input (GUI) impact in parallel of some independent business logic impact (a clock event for example). Therefore your process should be properly designed to handle such situations. Then the number of process engines shouldn't  matter.


<i>"I set the service task <code>async=true</code> it’s possible to get my expected behavior, but then <b>the message sender loses the execution control of the following tasks</b>."</i>
Now look on this <b>process definition (design) problem</b> from the perspective of a single engine: what is supposed to happen if two notifications happen simultaneously (for example invoked by independent clock events)? Should each of them process the instance to the end or one of them should give up and rely on the other event to continue (finish the process)? What will do two workers that grab the same wrench at the same time - will they stick on it? I, personally, doubt.


Thus said, I think that <i>"I set the service task <code>async=true</code>"</i> is a good starting point but then you <b>shouldn't rely</b> on <i>"the message sender loses</i> keeps <i>the execution control of the following tasks"</i>.
Getting started

Tags


Find what you came for

We want to make your experience in Hyland Connect as valuable as possible, so we put together some helpful links.