AnsweredAssumed Answered

Maybe a bug in messageEventReceived

Question asked by turael on Jul 27, 2017
Latest reply on Aug 7, 2017 by turael

Hello friends,

in our software we search in the hi_actinst table for some activities and sometimes we need to check (against the endtime) for a completed usertask. But this week we discovered a strange behavior:

if we send a message to usertask (with messageEventReceived) the endtime is set to the activities - we think thats not correct but we dont know exactly

So i made a simple BPMN and a testcase for you to check that behavior.

I hope you can help me with that - currently we got a workaround, so the bug is not critical for us

 

the test BPMN

<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="1.5.1">
  <bpmn:process id="endTimeBugTestBPMN" isExecutable="true">
    <bpmn:startEvent id="StartEvent_1">
      <bpmn:outgoing>SequenceFlow_05264a4</bpmn:outgoing>
    </bpmn:startEvent>
    <bpmn:sequenceFlow id="SequenceFlow_05264a4" sourceRef="StartEvent_1" targetRef="Task_0r58ed8" />
    <bpmn:endEvent id="EndEvent_0ho3g0v">
      <bpmn:incoming>SequenceFlow_1jav8nl</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:sequenceFlow id="SequenceFlow_1jav8nl" sourceRef="Task_0r58ed8" targetRef="EndEvent_0ho3g0v" />
    <bpmn:endEvent id="EndEvent_0eicala">
      <bpmn:incoming>SequenceFlow_1fo7atn</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:sequenceFlow id="SequenceFlow_1fo7atn" sourceRef="BoundaryEvent_16bcjdl" targetRef="EndEvent_0eicala" />
    <bpmn:userTask id="Task_0r58ed8" name="Testtask">
      <bpmn:incoming>SequenceFlow_05264a4</bpmn:incoming>
      <bpmn:outgoing>SequenceFlow_1jav8nl</bpmn:outgoing>
    </bpmn:userTask>
    <bpmn:boundaryEvent id="BoundaryEvent_16bcjdl" cancelActivity="false" attachedToRef="Task_0r58ed8">
      <bpmn:outgoing>SequenceFlow_1fo7atn</bpmn:outgoing>
      <bpmn:messageEventDefinition messageRef="Message_0avzdxe" />
    </bpmn:boundaryEvent>
  </bpmn:process>
  <bpmn:message id="Message_0avzdxe" name="Message_0mqt7n0" />
  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="endTimeBugTestBPMN">
      <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
        <dc:Bounds x="173" y="102" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="SequenceFlow_05264a4_di" bpmnElement="SequenceFlow_05264a4">
        <di:waypoint xsi:type="dc:Point" x="209" y="120" />
        <di:waypoint xsi:type="dc:Point" x="275" y="120" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="242" y="105" width="0" height="0" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="EndEvent_0ho3g0v_di" bpmnElement="EndEvent_0ho3g0v">
        <dc:Bounds x="443" y="102" width="36" height="36" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="461" y="138" width="0" height="0" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="SequenceFlow_1jav8nl_di" bpmnElement="SequenceFlow_1jav8nl">
        <di:waypoint xsi:type="dc:Point" x="375" y="120" />
        <di:waypoint xsi:type="dc:Point" x="443" y="120" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="409" y="105" width="0" height="0" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="EndEvent_0eicala_di" bpmnElement="EndEvent_0eicala">
        <dc:Bounds x="318" y="231" width="36" height="36" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="336" y="267" width="0" height="0" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="SequenceFlow_1fo7atn_di" bpmnElement="SequenceFlow_1fo7atn">
        <di:waypoint xsi:type="dc:Point" x="336" y="178" />
        <di:waypoint xsi:type="dc:Point" x="336" y="231" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="351" y="204.5" width="0" height="0" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="UserTask_0wgrwlf_di" bpmnElement="Task_0r58ed8">
        <dc:Bounds x="275" y="80" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="BoundaryEvent_13pb3ld_di" bpmnElement="BoundaryEvent_16bcjdl">
        <dc:Bounds x="318" y="142" width="36" height="36" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="336" y="178" width="0" height="0" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn:definitions>

 

 

Junit Testclass with some comments:


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.util.List;
import java.util.Optional;

import org.activiti.engine.HistoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.ActivitiRule;
import org.activiti.engine.test.Deployment;
import org.h2.tools.Server;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;

public class EndTimeBugTest {
     private static Server h2Server = null;

     @Rule
     public ActivitiRule activitiRule = new ActivitiRule();

     public EndTimeBugTest() {
          activitiRule.setConfigurationResource("/resources/activiti.cfg.xml");
     }

     @Test
     @Deployment(resources = { "de/gad/zkm/bpmn/BugDiagram.bpmn" })
     public void test() {
          RuntimeService rs = activitiRule.getRuntimeService();
          TaskService ts = activitiRule.getTaskService();
          HistoryService hs = activitiRule.getHistoryService();

          // Start new process instance
          ProcessInstance processInstance = rs.startProcessInstanceByKey(
                    "endTimeBugTestBPMN");
          assertNotNull(processInstance);

          // normal search
          Task task = ts.createTaskQuery().singleResult();
          assertEquals("Testtask", task.getName());

          // look for the historic taskinstance
          HistoricTaskInstance hsTask = hs.createHistoricTaskInstanceQuery().singleResult();
          // end time should be null
          assertNull(hsTask.getEndTime());

          // look for the activities
          List<HistoricActivityInstance> activities = hs.createHistoricActivityInstanceQuery().list();
          assertEquals(2, activities.size());

          // Get task of all activities
          Optional<HistoricActivityInstance> taskActivity = activities.stream()
                    .filter(a -> a.getActivityId().equals("Task_0r58ed8")).findFirst();
          assertTrue(taskActivity.isPresent());

          // end time should be null too
          assertNull(taskActivity.get().getEndTime());

          // Now do the bug and send a message to Testtask execution
          rs.messageEventReceived("Message_0mqt7n0", task.getExecutionId());

          // now test again
          // look for the historic taskinstance
          hsTask = hs.createHistoricTaskInstanceQuery().singleResult();
          // end time should be null
          assertNull(hsTask.getEndTime());

          // look for the activities
          activities = hs.createHistoricActivityInstanceQuery().list();
          assertEquals(4, activities.size());

          // Get task of all activities
          taskActivity = activities.stream()
                    .filter(a -> a.getActivityId().equals("Task_0r58ed8")).findFirst();
          assertTrue(taskActivity.isPresent());

          // end time should be null too but it was set after i called
          // messageEventReceived
          assertNull(taskActivity.get().getEndTime()); // Error

     }

     @BeforeClass
     public static void setUpBeforeClass() throws Exception {

          try {
               // start H2 database
               h2Server = Server.createWebServer().start();
               System.out.println(h2Server.getURL());
          } catch (Exception e) {
               System.err.println(e);
          }
     }

     @AfterClass
     public static void setUpAfterClass() {
          // stop H2 database
          if (h2Server != null) {
               h2Server.stop();
          }

     }
}

Outcomes