AnsweredAssumed Answered

Event listener with async service task does not update service

Question asked by mishamo on Jun 17, 2014
Latest reply on Jan 26, 2016 by jbarrez
Hi,

I am trying to use an event listener to update my UI when an unclaimed task becomes available in the workflow. While events are coming through, this does not seem to be reflected in the services when queried. This seems to be an issue that is more pertinent when using async tasks and the job executor. I have created a test case to prove this:


import java.util.List;

import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.delegate.event.ActivitiEvent;
import org.activiti.engine.delegate.event.ActivitiEventListener;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.ActivitiRule;
import org.activiti.engine.test.Deployment;
import org.junit.Rule;
import org.junit.Test;

import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;

public class UpdateOnEventFailTest {

  @Rule
  public ActivitiRule activitiRule = new ActivitiRule("processupdatebug.activiti.cfg.xml");

  private volatile boolean passed;
  private List<Task> unclaimedTasks;

  @Test
  @Deployment(resources = "UpdateFailProcess.bpmn20.xml")
  public void testName() throws Exception {
    RuntimeService runtimeService = activitiRule.getRuntimeService();
    runtimeService.addEventListener(eventListener);

    runtimeService.startProcessInstanceByKey("myProcess");

    //required to let the job executor finish anything that it was doing
    Thread.sleep(2000);

    runtimeService.removeEventListener(eventListener);

    assertThat(passed, is(true));
  }

  private final ActivitiEventListener eventListener = new ActivitiEventListener() {
    @Override
    public void onEvent(ActivitiEvent activitiEvent) {
      System.err.println(activitiEvent.getType());
      doUpdate();
    }

    @Override
    public boolean isFailOnException() {
      return false;
    }
  };

  private void doUpdate() {
    TaskService taskService = activitiRule.getTaskService();
    unclaimedTasks = taskService.createTaskQuery()
                                 .taskUnassigned()
                                 .active()
                                 .list();

    if(unclaimedTasks.size() > 0) {
      passed = true;
      System.err.println("TEST PASSED");
    }
  }
}



<?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="myProcess" name="My process" isExecutable="true">
    <userTask id="usertask1" name="Unclaimed Task"></userTask>
    <serviceTask id="servicetask1" name="Service Task" activiti:async="true" activiti:class="process.processupdatebug.ProcessUpdateTaskDelegate"></serviceTask>
    <sequenceFlow id="flow1" sourceRef="servicetask1" targetRef="usertask1"></sequenceFlow>
    <startEvent id="startevent1" name="Start"></startEvent>
    <sequenceFlow id="flow2" sourceRef="startevent1" targetRef="servicetask1"></sequenceFlow>
    <endEvent id="endevent1" name="End"></endEvent>
    <sequenceFlow id="flow3" sourceRef="usertask1" targetRef="endevent1"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_myProcess">
    <bpmndi:BPMNPlane bpmnElement="myProcess" id="BPMNPlane_myProcess">
      <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
        <omgdc:Bounds height="55.0" width="105.0" x="682.0" y="290.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="servicetask1" id="BPMNShape_servicetask1">
        <omgdc:Bounds height="55.0" width="105.0" x="480.0" y="290.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="330.0" y="300.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="900.0" y="300.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
        <omgdi:waypoint x="585.0" y="317.0"></omgdi:waypoint>
        <omgdi:waypoint x="682.0" y="317.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
        <omgdi:waypoint x="365.0" y="317.0"></omgdi:waypoint>
        <omgdi:waypoint x="480.0" y="317.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
        <omgdi:waypoint x="787.0" y="317.0"></omgdi:waypoint>
        <omgdi:waypoint x="900.0" y="317.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>



<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans.xsd">

  <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">

    <property name="jdbcUrl" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000" />
    <property name="jdbcDriver" value="org.h2.Driver" />
    <property name="jdbcUsername" value="sa" />
    <property name="jdbcPassword" value="" />

    <property name="jobExecutorActivate" value="true" />

    <property name="databaseSchemaUpdate" value="true" />

  </bean>

</beans>



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

public class ProcessUpdateTaskDelegate implements JavaDelegate {

  @Override
  public void execute(DelegateExecution execution) throws Exception {

  }
}


Points to notice are that the service task has "async=true" set, the config has "jobExecutorActivate = true" set and the test requires a sleep for a second or two to allow the job executor to complete anything in the pipeline before shutting the engine down. Basically, the state I am expecting is for the unclaimed tasks to be of size 1 as the workflow should have moved on to the user task (having finished the empty service task). The interesting thing is that all the appropriate events are fired (ACTIVITY_STARTED, ACTIVITY_COMPLETED and JOB_EXECUTION_SUCCESS) but that the list of unclaimed tasks never reflects this.

Outcomes