AnsweredAssumed Answered

Timer fired every 5 minutes while executing a long running command

Question asked by nchan on Nov 14, 2014
Latest reply on Nov 20, 2014 by jbarrez
Activiti version  tested : 5.16 and 5.10

I have a simple workflow with a timer catching event and a long running task attached to it.

START — TimerCatchingEvent (PT10S Intermediate Event) — ScriptTask (Long running - runs for more than 5 min) — END

The script task runs for more than 5 minutes. While this happens, the timer is getting fired again and again every 5 min (approx). I don't have time cycle set. Enclosed the BPMN file.

What am i missing here, please?

Note: This is just a sample project i have created for the post. This timer is part of a bigger workflow (sitting inside a sub workflow) and behaves exactly the same way i explained here.


<?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="myProcess" name="My process" isExecutable="true">
    <startEvent id="startevent1" name="Start"></startEvent>
    <intermediateCatchEvent id="timerintermediatecatchevent3" name="TimerCatchEvent">
      <timerEventDefinition>
        <timeDuration>PT10S</timeDuration>
      </timerEventDefinition>
    </intermediateCatchEvent>
    <sequenceFlow id="flow24" sourceRef="timerintermediatecatchevent3" targetRef="scripttask5"></sequenceFlow>
    <scriptTask id="scripttask5" name="Long running command" scriptFormat="groovy" activiti:autoStoreVariables="false">
      <script>println "Running command .."
def y = 5000000

while ( y– &gt; 0 ) {
    def command = """find . -name "*.*" -print"""   
    def proc = command.execute()   
    proc.waitFor()   
    if( y % 50000 == 0) println  Thread.currentThread().getId() + " – " + " Still running …" + y
}
print "Completed running command"</script>
    </scriptTask>
    <sequenceFlow id="flow25" sourceRef="scripttask5" targetRef="endevent2"></sequenceFlow>
    <endEvent id="endevent2" name="End">
    </endEvent>
    <sequenceFlow id="flow26" sourceRef="startevent1" targetRef="timerintermediatecatchevent3"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_myProcess">
    <bpmndi:BPMNPlane bpmnElement="myProcess" id="BPMNPlane_myProcess">
      <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="210.0" y="70.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="timerintermediatecatchevent3" id="BPMNShape_timerintermediatecatchevent3">
        <omgdc:Bounds height="35.0" width="35.0" x="290.0" y="70.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="scripttask5" id="BPMNShape_scripttask5">
        <omgdc:Bounds height="71.0" width="105.0" x="360.0" y="52.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="endevent2" id="BPMNShape_endevent2">
        <omgdc:Bounds height="35.0" width="35.0" x="530.0" y="70.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="flow24" id="BPMNEdge_flow24">
        <omgdi:waypoint x="325.0" y="87.0"></omgdi:waypoint>
        <omgdi:waypoint x="360.0" y="87.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow25" id="BPMNEdge_flow25">
        <omgdi:waypoint x="465.0" y="87.0"></omgdi:waypoint>
        <omgdi:waypoint x="530.0" y="87.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow26" id="BPMNEdge_flow26">
        <omgdi:waypoint x="245.0" y="87.0"></omgdi:waypoint>
        <omgdi:waypoint x="290.0" y="87.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

Here is the unit test that runs this code:

package org.activiti.designer.test;

import static org.junit.Assert.*;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import java.io.FileInputStream;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.test.ActivitiRule;
import org.junit.Rule;
import org.junit.Test;


public class ProcessTestMyProcess {

   private Logger LOG = Logger.getLogger(ProcessTestMyProcess.class.getName());
   private String filename = "/Users/nchan/Projects/eclipse-ws/luna-groovy/ezcommit/cca-workflow-mock/src/main/resources/diagrams/mock-workflow.bpmn";
   
   private String PROCESS_MAIN = "myProcess";

   @Rule
   public ActivitiRule activitiRule = new ActivitiRule();

   @Test
   public void startProcess() throws Exception {
      RepositoryService repositoryService = activitiRule.getRepositoryService();
      repositoryService.createDeployment().addInputStream("myProcess.bpmn20.xml",
            new FileInputStream(filename)).deploy();
      RuntimeService runtimeService = activitiRule.getRuntimeService();
      
      Map<String, Object> variableMap = new HashMap<String, Object>();
      variableMap.put("name", "Activiti");
      ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myProcess", variableMap);
      
      int waitCnt = 0;
      LOG.info("Thread:" + Thread.currentThread().getId() + " – Started process instance @" + new Date());
   
      while (isWorkflowActive(runtimeService)) {
            LOG.info("workflow running …" + ++waitCnt + "@" + new Date());
            //wait for specified duration and check again
            Thread.sleep(10000);
        }
      
      LOG.info("Thread:" + Thread.currentThread().getId() + " – Ended process instance @" + new Date());
      assertNotNull(processInstance.getId());
      System.out.println("id " + processInstance.getId() + " "
            + processInstance.getProcessDefinitionId());
   }
   
   private final boolean isWorkflowActive(RuntimeService runtimeService) {
      ProcessInstance pi = runtimeService.createProcessInstanceQuery()
            .processDefinitionKey(PROCESS_MAIN)
            .singleResult();
      if (pi != null) {
         return !pi.isEnded();
      } else {
         return false;
      }
   }
}

Here is my activiti.cfg.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
   
   <bean id="processEngineConfiguration"
      class="org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">
      <property name="databaseSchemaUpdate" value="true" />
      <property name="jobExecutorActivate" value="true" />
   </bean>

   <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
      <property name="processEngineConfiguration" ref="processEngineConfiguration" />
   </bean>
   
   <bean id="runtimeService" factory-bean="processEngine"
      factory-method="getRuntimeService" />

</beans>

Outcomes