AnsweredAssumed Answered

Upgrade from 5.7 to 5.10 concurrency issues

Question asked by walterjs on Oct 5, 2012
Latest reply on Oct 5, 2012 by ronald.van.kuijk
Hi there,

We have had a test running for almost a year without ever failing. I recently upgraded our engine from 5.7 to 5.10 and suddenly the test started failing intermittently. The test is specifically to test the RetryInterceptor for OptimiticLockingExceptions. Here is the stack trace. On line 155, the only thing that can cause an NPE is that the execution is null:


java.lang.NullPointerException
   at org.activiti.engine.impl.persistence.entity.TaskEntity.complete(TaskEntity.java:155)
   at org.activiti.engine.impl.cmd.CompleteTaskCmd.completeTask(CompleteTaskCmd.java:63)
   at org.activiti.engine.impl.cmd.CompleteTaskCmd.execute(CompleteTaskCmd.java:57)
   at org.activiti.engine.impl.cmd.CompleteTaskCmd.execute(CompleteTaskCmd.java:28)
   at org.activiti.engine.impl.interceptor.CommandExecutorImpl.execute(CommandExecutorImpl.java:24)
   at org.activiti.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:42)
   at org.activiti.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:33)
   at org.activiti.engine.impl.interceptor.RetryInterceptor.execute(RetryInterceptor.java:50)
   at org.activiti.engine.impl.TaskServiceImpl.complete(TaskServiceImpl.java:144)
   at OptimisticLockingTest.testConcurrentTransactions(OptimisticLockingTest.java:51)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

Here is the test:

import java.util.List;

import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.Deployment;
import org.activiti.spring.impl.test.SpringActivitiTestCase;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;

@SuppressWarnings({"SpringJavaAutowiringInspection"})
@ContextConfiguration("classpath:process-test-context.xml")
//@Ignore("This started failing intermittently after 5.10 upgrade")
public class OptimisticLockingTest extends SpringActivitiTestCase {

    @Autowired private RuntimeService runtimeService;
    @Autowired private TaskService taskService;

    @Before
    public void setUp() {
        runtimeService.startProcessInstanceByKey("process-entries-test");
    }

    @Test
    @Deployment(resources = {"process-entries-test.activiti.bpmn"})
    public void testConcurrentTransactions() throws InterruptedException {
        List<Task> tasks = taskService.createTaskQuery().list();

        // complete the first task
        for (Task task : tasks) {
            taskService.complete(task.getId());
        }

        final List<Task> concurrentTasks = taskService.createTaskQuery().list();

        assertEquals(2, concurrentTasks.size());

        Thread t = new Thread() {
            public void run() {
                taskService.complete(concurrentTasks.get(0).getId());
            }
        };
        t.start();

        Thread.sleep(1);

        taskService.complete(concurrentTasks.get(1).getId());

        t.join();

        assertTrue("All tasks should have been completed", taskService.createTaskQuery().list().isEmpty());

    }
}


And here is the process:

<?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: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="process-entries-test" name="process-entries-test">
    <userTask id="usertask1" name="Task1" activiti:assignee="kermit"></userTask>
    <userTask id="usertask2" name="Task2" activiti:assignee="kermit"></userTask>
    <userTask id="usertask3" name="User Task" activiti:candidateGroups="sales"></userTask>
    <sequenceFlow id="flow2" name="" sourceRef="parallelgateway1" targetRef="usertask1"></sequenceFlow>
    <sequenceFlow id="flow3" name="" sourceRef="parallelgateway1" targetRef="usertask2"></sequenceFlow>
    <sequenceFlow id="flow6" name="" sourceRef="usertask3" targetRef="parallelgateway1"></sequenceFlow>
    <parallelGateway id="parallelgateway1" name="Parallel Gateway"></parallelGateway>
    <startEvent id="startevent1" name="Start"></startEvent>
    <sequenceFlow id="flow7" name="" sourceRef="startevent1" targetRef="usertask3"></sequenceFlow>
    <endEvent id="endevent1" name="End"></endEvent>
    <sequenceFlow id="flow8" name="" sourceRef="usertask1" targetRef="endevent1"></sequenceFlow>
    <sequenceFlow id="flow9" name="" sourceRef="usertask2" targetRef="endevent1"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_process-entries-test">
    <bpmndi:BPMNPlane bpmnElement="process-entries-test" id="BPMNPlane_process-entries-test">
      <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
        <omgdc:Bounds height="55" width="105" x="460" y="100"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
        <omgdc:Bounds height="55" width="105" x="460" y="251"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3">
        <omgdc:Bounds height="55" width="105" x="235" y="171"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="parallelgateway1" id="BPMNShape_parallelgateway1">
        <omgdc:Bounds height="40" width="40" x="372" y="178"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
        <omgdc:Bounds height="35" width="35" x="130" y="181"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
        <omgdc:Bounds height="35" width="35" x="600" y="181"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
        <omgdi:waypoint x="392" y="178"></omgdi:waypoint>
        <omgdi:waypoint x="391" y="127"></omgdi:waypoint>
        <omgdi:waypoint x="460" y="127"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
        <omgdi:waypoint x="392" y="218"></omgdi:waypoint>
        <omgdi:waypoint x="391" y="278"></omgdi:waypoint>
        <omgdi:waypoint x="460" y="278"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6">
        <omgdi:waypoint x="340" y="198"></omgdi:waypoint>
        <omgdi:waypoint x="372" y="198"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow7" id="BPMNEdge_flow7">
        <omgdi:waypoint x="165" y="198"></omgdi:waypoint>
        <omgdi:waypoint x="235" y="198"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow8" id="BPMNEdge_flow8">
        <omgdi:waypoint x="565" y="127"></omgdi:waypoint>
        <omgdi:waypoint x="617" y="127"></omgdi:waypoint>
        <omgdi:waypoint x="617" y="181"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow9" id="BPMNEdge_flow9">
        <omgdi:waypoint x="565" y="278"></omgdi:waypoint>
        <omgdi:waypoint x="617" y="279"></omgdi:waypoint>
        <omgdi:waypoint x="617" y="216"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

Outcomes