AnsweredAssumed Answered

Error waking up a receice task with a boundary timer event

Question asked by danilo1 on Oct 18, 2013
Latest reply on Jul 10, 2014 by trademak
Hi,

In my process I have a Receive Task that wait for an external signal made by activiti rest api.
It works fine, but If I associate to that task a boundary timer to simulate a timeout:
- if the timer fires is ok calling the next task,
- if the signal arrives before the timeout an internal exception is raised.

the 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: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">
  <signal id="MySignal" name="My Signal"></signal>
  <process id="checkSignalKey" name="Check signal" isExecutable="true">
    <startEvent id="startevent1" name="Start"></startEvent>
    <endEvent id="endevent1" name="End"></endEvent>
    <scriptTask id="startingTask" name="First Task" scriptFormat="groovy" activiti:autoStoreVariables="true">
      <script>println(   execution.getActivityId() )

import java.util.Date;
import org.activiti.engine.ActivitiException;


      try  {
         String pushedVar = (String) execution.getVariable("pushedVar");
         if(pushedVar == null)
            pushedVar="";
         System.out.println (   "process: " + execution.getProcessInstanceId()  + " activity : " +   execution.getCurrentActivityId()  + " -  time: " +  new Date().getTime()   + " -  pushedVar :" +  pushedVar    );
      }  catch ( ActivitiException e ) {
         e.printStackTrace();
      }

println(   execution.getActivityId() )</script>
    </scriptTask>
    <scriptTask id="lastTask" name="Last Task" scriptFormat="groovy" activiti:autoStoreVariables="true">
      <script>println(   execution.getActivityId() )

import java.util.Date;
import org.activiti.engine.ActivitiException;


         try  {
         String pushedVar = (String) execution.getVariable("pushedVar");
         if(pushedVar == null)
            pushedVar="";
         System.out.println (   "process: " + execution.getProcessInstanceId()  + " activity : " +   execution.getCurrentActivityId()  + " -  time: " +  new Date().getTime()   +  " -  pushedVar :" +  pushedVar    );
      }  catch ( ActivitiException e ) {
         e.printStackTrace();
      }

println(   execution.getActivityId() )</script>
    </scriptTask>
    <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="startingTask"></sequenceFlow>
    <sequenceFlow id="flow4" sourceRef="lastTask" targetRef="endevent1"></sequenceFlow>
    <receiveTask id="receivetask1" name="Receive Task"></receiveTask>
    <sequenceFlow id="flow14" sourceRef="startingTask" targetRef="receivetask1"></sequenceFlow>
    <sequenceFlow id="flow15" sourceRef="receivetask1" targetRef="lastTask"></sequenceFlow>
    <boundaryEvent id="boundarytimer1" name="Timer" attachedToRef="receivetask1" cancelActivity="true">
      <timerEventDefinition>
        <timeDuration>PT5S</timeDuration>
      </timerEventDefinition>
    </boundaryEvent>
    <scriptTask id="anotherTask" name="Another Task" scriptFormat="groovy" activiti:autoStoreVariables="true">
      <script>println(   execution.getActivityId() )

import java.util.Date;
import org.activiti.engine.ActivitiException;


         try  {
         String pushedVar = (String) execution.getVariable("pushedVar");
         if(pushedVar == null)
            pushedVar="";
         System.out.println (   "process: " + execution.getProcessInstanceId()  + " activity : " +   execution.getCurrentActivityId()  + " -  time: " +  new Date().getTime()   +  " -  pushedVar :" +  pushedVar    );
      }  catch ( ActivitiException e ) {
         e.printStackTrace();
      }

println(   execution.getActivityId() )</script>
    </scriptTask>
    <sequenceFlow id="flow16" sourceRef="boundarytimer1" targetRef="anotherTask"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_checkSignalKey">
    <bpmndi:BPMNPlane bpmnElement="checkSignalKey" id="BPMNPlane_checkSignalKey">
      <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="30.0" y="40.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="620.0" y="40.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="startingTask" id="BPMNShape_startingTask">
        <omgdc:Bounds height="55.0" width="105.0" x="100.0" y="30.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="lastTask" id="BPMNShape_lastTask">
        <omgdc:Bounds height="55.0" width="105.0" x="480.0" y="30.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="receivetask1" id="BPMNShape_receivetask1">
        <omgdc:Bounds height="55.0" width="105.0" x="280.0" y="120.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="boundarytimer1" id="BPMNShape_boundarytimer1">
        <omgdc:Bounds height="30.0" width="30.0" x="330.0" y="170.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="anotherTask" id="BPMNShape_anotherTask">
        <omgdc:Bounds height="61.0" width="151.0" x="470.0" y="270.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
        <omgdi:waypoint x="65.0" y="57.0"></omgdi:waypoint>
        <omgdi:waypoint x="100.0" y="57.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
        <omgdi:waypoint x="585.0" y="57.0"></omgdi:waypoint>
        <omgdi:waypoint x="620.0" y="57.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow14" id="BPMNEdge_flow14">
        <omgdi:waypoint x="152.0" y="85.0"></omgdi:waypoint>
        <omgdi:waypoint x="332.0" y="120.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow16" id="BPMNEdge_flow16">
        <omgdi:waypoint x="345.0" y="200.0"></omgdi:waypoint>
        <omgdi:waypoint x="545.0" y="270.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow15" id="BPMNEdge_flow15">
        <omgdi:waypoint x="332.0" y="120.0"></omgdi:waypoint>
        <omgdi:waypoint x="532.0" y="85.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>




And the unit test code (the Thread.sleep is used unly to avoid that method ends before the activiti runned process. ):

   @Test
   @Deployment(resources = "CheckSignal.bpmn")
   public void checkSignal() throws Exception {
      String processKey = "checkSignalKey";

      // start process
      String reply = startProcess(processKey, null);
      Map<String, Object> map = getJsonValues(reply);
      String idProcess = (String) map.get("id");

      sendSignal(idProcess, null);
      
      
      
      // get if instance exists
      long secs = 0;
      do {
         Thread.sleep(1000);
         if ( (secs ++ ) > 10 ){
            throw new Exception("Timeout test. ");
         }
      } while (processExists(idProcess));

      return;
   }

   @Test
   @Deployment(resources = "CheckSignal.bpmn")
   public void checkSignalEventWithVars() throws Exception {
      String processKey = "checkSignalKey";

      // start process
      List<ProcessVariable> vars = new ArrayList<ProcessVariable>();
      vars.add(new ProcessVariable("pushedVar", "[A simple string variable]", "string"));
      
      String reply = startProcess(processKey, vars);
      Map<String, Object> map = getJsonValues(reply);
      String idProcess = (String) map.get("id");
      
      long secs = 2;
      System.out.println( "wait for " + secs + " seconds" );
      Thread.sleep(secs * 1000);

      vars.clear();
      vars.add(new ProcessVariable("pushedVar", "[The simple string variable is modified]", "string"));
      sendSignalEvent(idProcess, "My Signal", vars);
      
      // get if instance exists
      secs = 0;
      do {
         Thread.sleep(1000);
         if ( (secs ++ ) > 10 ){
            throw new Exception("Timeout test. ");
         }
      } while (processExists(idProcess));

      return;
   }



Is it a normal error?
As workaround i could move the timer in another process that is started by the principal when needs and wake up the first but I don't like it.


Thanks.

Outcomes