AnsweredAssumed Answered

async parallel/inclusive gateways

Question asked by rickm on Nov 11, 2014
Hi,

I recently saw in a posting on Tijs' blog (http://bpmn20inaction.blogspot.com/2014/07/activiti-516-feature-preview.html) that the solution for joining of parallel/inclusive gateways had been cleaned up in 5.16 so that it was not necessary to use external frameworks to address the issue of optimistic locks.   This all looks great, but I can't seem to get it to work, I'm still seeing the ActivitiOptimisticLockingException. 

TIA,
Rick

My environment is:
- Activiti 5.16.4
- JRE 1.7
- Tomcat 8.0
- Eclipse Luna
- H2

Below is the content of my source:

Process2.bpmn
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
  <process id="Process2" name="Process2" isExecutable="true">
    <startEvent id="startevent1" name="Start"></startEvent>
    <parallelGateway id="parallelgateway1" name="Parallel Gateway"></parallelGateway>
    <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="parallelgateway1"></sequenceFlow>
    <serviceTask id="Task2" name="Task 2" activiti:async="true" activiti:exclusive="false" activiti:class="tasks.Task_Test"></serviceTask>
    <sequenceFlow id="flow2" sourceRef="parallelgateway1" targetRef="Task2"></sequenceFlow>
    <serviceTask id="Task1" name="Task 1" activiti:async="true" activiti:exclusive="false" activiti:class="tasks.Task_Test"></serviceTask>
    <sequenceFlow id="flow3" sourceRef="parallelgateway1" targetRef="Task1"></sequenceFlow>
    <parallelGateway id="parallelgateway2" name="Parallel Gateway" activiti:async="true" activiti:exclusive="true"></parallelGateway>
    <sequenceFlow id="flow4" sourceRef="Task1" targetRef="parallelgateway2"></sequenceFlow>
    <sequenceFlow id="flow5" sourceRef="Task2" targetRef="parallelgateway2"></sequenceFlow>
    <endEvent id="endevent1" name="End"></endEvent>
    <sequenceFlow id="flow6" sourceRef="parallelgateway2" targetRef="endevent1"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_Process2">
    <bpmndi:BPMNPlane bpmnElement="Process2" id="BPMNPlane_Process2">
      <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="150.0" y="319.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="parallelgateway1" id="BPMNShape_parallelgateway1">
        <omgdc:Bounds height="40.0" width="40.0" x="220.0" y="316.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="Task2" id="BPMNShape_Task2">
        <omgdc:Bounds height="55.0" width="105.0" x="290.0" y="390.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="Task1" id="BPMNShape_Task1">
        <omgdc:Bounds height="55.0" width="105.0" x="290.0" y="230.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="parallelgateway2" id="BPMNShape_parallelgateway2">
        <omgdc:Bounds height="40.0" width="40.0" x="430.0" y="316.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="510.0" y="319.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
        <omgdi:waypoint x="185.0" y="336.0"></omgdi:waypoint>
        <omgdi:waypoint x="220.0" y="336.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
        <omgdi:waypoint x="240.0" y="356.0"></omgdi:waypoint>
        <omgdi:waypoint x="240.0" y="417.0"></omgdi:waypoint>
        <omgdi:waypoint x="290.0" y="417.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
        <omgdi:waypoint x="240.0" y="316.0"></omgdi:waypoint>
        <omgdi:waypoint x="240.0" y="257.0"></omgdi:waypoint>
        <omgdi:waypoint x="290.0" y="257.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
        <omgdi:waypoint x="395.0" y="257.0"></omgdi:waypoint>
        <omgdi:waypoint x="450.0" y="257.0"></omgdi:waypoint>
        <omgdi:waypoint x="450.0" y="316.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5">
        <omgdi:waypoint x="395.0" y="417.0"></omgdi:waypoint>
        <omgdi:waypoint x="450.0" y="417.0"></omgdi:waypoint>
        <omgdi:waypoint x="450.0" y="356.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6">
        <omgdi:waypoint x="470.0" y="336.0"></omgdi:waypoint>
        <omgdi:waypoint x="510.0" y="336.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:Enplane>
  </bpmndi:BPMNDiagram>
</definitions>

Task_Test.java:
package tasks;

import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.JavaDelegate;


public class Task_Test implements JavaDelegate {

   @Override
   public void execute(DelegateExecution context) throws Exception {
      System.out.println("Executing activity: " + context.getCurrentActivityName());
      
      Thread.sleep(100);
   }
}

Console:
Starting Process ID Process2
Executing activity: Task 1
Executing activity: Task 2
Exception in thread "pool-1-thread-2" org.activiti.engine.ActivitiOptimisticLockingException: ProcessInstance[8505] was updated by another transaction concurrently
   at org.activiti.engine.impl.db.DbSqlSession.flushUpdates(DbSqlSession.java:562)
   at org.activiti.engine.impl.db.DbSqlSession.flush(DbSqlSession.java:444)
   at org.activiti.engine.impl.interceptor.CommandContext.flushSessions(CommandContext.java:170)
   at org.activiti.engine.impl.interceptor.CommandContext.close(CommandContext.java:117)
   at org.activiti.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:66)
   at org.activiti.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:31)
   at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:40)
   at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:35)
   at org.activiti.engine.impl.jobexecutor.ExecuteJobsRunnable.run(ExecuteJobsRunnable.java:46)
   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)

Outcomes