cancel
Showing results for 
Search instead for 
Did you mean: 

Problem in understanding execution order of tasks

fellowtom
Champ in-the-making
Champ in-the-making
Hi all,

I'm trying to embedd the activiti engine in our own project (activiti 5.13). This works well so far. But I'm having some 'missunderstoodment' in which order the tasks are executed. So in my java-code I define how the usertask is handled and then completed.
My process has a timer-event, too. The problem is, that the java-code is executed and the usertask is completed, although this should just happen after the timer is triggered. What do I have to change to let the user tasks wait untill my timer fired? Of cause I could solve it in having a variable which looks if timer-event was done, but that's not the aim (because its a logical sequence flow), isnt it?

Process:  Start->Timer->UserTask->End

Actually I get all user-output and then the timer ticks.
The code is like the 10-Minute-Tutorial. No changes to user task handling.
I'm glad for every hint that helps sovling my problem.

With kind regards,
FellowTom
9 REPLIES 9

jbarrez
Star Contributor
Star Contributor
That should be default behavior…. Do you have the jobexecutor running? Can you share your process xml so we can see what you're trying.

fellowtom
Champ in-the-making
Champ in-the-making
Hi,

thanks for your reply. Yes the jobexecutor is running. Dont try to see a deepinger meaning in that process, its just a example for components. At the end I found out, that it would be possible to simulate all usertasks as service tasks. This would avoid the problem, but is no good solution.  Here my java code and process xml.


            // Create Activiti process engine
     ProcessEngine processEngine = ProcessEngineConfiguration
      .createStandaloneProcessEngineConfiguration()
      .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE)
      .setJobExecutorActivate(true)
      .buildProcessEngine();
    
     // Get Activiti services
     RepositoryService repositoryService = processEngine.getRepositoryService();
     RuntimeService runtimeService = processEngine.getRuntimeService();
    
     // Deploy the process definition
     repositoryService.createDeployment()
        .addClasspathResource("MyProcess2.bpmn")
        .deploy();
    
     // Start a process instance
     String procId = runtimeService.startProcessInstanceByKey("myProcess2").getId();
    
     // Get the first task
     TaskService taskService = processEngine.getTaskService();
     List<Task> tasks = taskService.createTaskQuery().taskAssignee("Worker1").list();
     for (Task task : tasks)
     {
      System.out.println("Following task is available for Worker No.1: " + task.getName());
      // claim that task
      taskService.claim(task.getId(), "Worker1");
     }
     // Verify Worker1 can now retrieve the task
     tasks = taskService.createTaskQuery().taskAssignee("Worker1").list();
     for (Task task : tasks)
     {
      System.out.println("Task for Worker No.1: " + task.getName());
      // Complete the task     
      taskService.complete(task.getId());
      System.out.println("Task completed.");
     }

<?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" xmlnsSmiley Surprisedmgdc="http://www.omg.org/spec/DD/20100524/DC" xmlnsSmiley Surprisedmgdi="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="myProcess2" name="My process" isExecutable="true">
    <startEvent id="startevent1" name="Start"></startEvent>
    <scriptTask id="scripttask1" name="Script Task" scriptFormat="groovy" activiti:autoStoreVariables="true">
      <script>outSmiley Tonguerintln "started"
execution.setVariable("counter",0)</script>
    </scriptTask>
    <endEvent id="endevent1" name="End"></endEvent>
    <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="scripttask1"></sequenceFlow>
    <sequenceFlow id="flow2" sourceRef="scripttask1" targetRef="parallelgateway1"></sequenceFlow>
    <intermediateCatchEvent id="timerintermediatecatchevent1" name="TimerCatchEvent">
      <timerEventDefinition>
        <timeDuration>PT10S</timeDuration>
      </timerEventDefinition>
    </intermediateCatchEvent>
    <scriptTask id="scripttask2" name="Script Task" scriptFormat="groovy" activiti:autoStoreVariables="true">
      <script>outSmiley Tonguerintln "ended"</script>
    </scriptTask>
    <sequenceFlow id="flow3" sourceRef="parallelgateway2" targetRef="scripttask5"></sequenceFlow>
    <sequenceFlow id="flow4" sourceRef="scripttask2" targetRef="endevent1"></sequenceFlow>
    <parallelGateway id="parallelgateway1" name="Parallel Gateway"></parallelGateway>
    <parallelGateway id="parallelgateway2" name="Parallel Gateway"></parallelGateway>
    <scriptTask id="scripttask3" name="Script Task" scriptFormat="groovy" activiti:autoStoreVariables="true">
      <script>outSmiley Tonguerintln "I'm done in parallel"</script>
    </scriptTask>
    <sequenceFlow id="flow5" sourceRef="parallelgateway1" targetRef="timerintermediatecatchevent1"></sequenceFlow>
    <sequenceFlow id="flow6" sourceRef="parallelgateway1" targetRef="scripttask3"></sequenceFlow>
    <sequenceFlow id="flow7" sourceRef="scripttask3" targetRef="parallelgateway2"></sequenceFlow>
    <sequenceFlow id="flow8" sourceRef="timerintermediatecatchevent1" targetRef="parallelgateway2"></sequenceFlow>
    <scriptTask id="scripttask4" name="Script Task" scriptFormat="groovy" activiti:autoStoreVariables="true">
      <script>counter=counter+1
outSmiley Tonguerintln ("Counter-Value: "+counter)</script>
    </scriptTask>
    <exclusiveGateway id="exclusivegateway1" name="Exclusive Gateway"></exclusiveGateway>
    <sequenceFlow id="flow9" sourceRef="parallelgateway1" targetRef="scripttask4"></sequenceFlow>
    <sequenceFlow id="flow10" sourceRef="scripttask4" targetRef="exclusivegateway1"></sequenceFlow>
    <sequenceFlow id="flow11" name="counter=10" sourceRef="exclusivegateway1" targetRef="parallelgateway2">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${counter>=10}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="flow12" name="counter&lt;10" sourceRef="exclusivegateway1" targetRef="scripttask4">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${counter<10}]]></conditionExpression>
    </sequenceFlow>
    <scriptTask id="scripttask5" name="Script Task" scriptFormat="groovy" activiti:autoStoreVariables="true">
      <script>outSmiley Tonguerintln "10secs are up"</script>
    </scriptTask>
    <userTask id="usertask1" name="User Task 1" activiti:assignee="Worker1"></userTask>
    <sequenceFlow id="flow13" sourceRef="scripttask5" targetRef="usertask1"></sequenceFlow>
    <sequenceFlow id="flow14" sourceRef="usertask1" targetRef="usertask2"></sequenceFlow>
    <userTask id="usertask2" name="User Task 2" activiti:assignee="Worker1"></userTask>
    <sequenceFlow id="flow15" sourceRef="usertask2" targetRef="scripttask2"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_myProcess2">
    <bpmndi:BPMNPlane bpmnElement="myProcess2" id="BPMNPlane_myProcess2">
      <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="10.0" y="50.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="scripttask1" id="BPMNShape_scripttask1">
        <omgdc:Bounds height="55.0" width="105.0" x="62.0" y="40.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="725.0" y="230.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="timerintermediatecatchevent1" id="BPMNShape_timerintermediatecatchevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="284.0" y="9.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="scripttask2" id="BPMNShape_scripttask2">
        <omgdc:Bounds height="55.0" width="105.0" x="596.0" y="220.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="parallelgateway1" id="BPMNShape_parallelgateway1">
        <omgdc:Bounds height="40.0" width="40.0" x="189.0" y="47.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="parallelgateway2" id="BPMNShape_parallelgateway2">
        <omgdc:Bounds height="40.0" width="40.0" x="379.0" y="47.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="scripttask3" id="BPMNShape_scripttask3">
        <omgdc:Bounds height="55.0" width="105.0" x="249.0" y="80.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="scripttask4" id="BPMNShape_scripttask4">
        <omgdc:Bounds height="55.0" width="105.0" x="249.0" y="160.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="exclusivegateway1" id="BPMNShape_exclusivegateway1">
        <omgdc:Bounds height="40.0" width="40.0" x="377.0" y="167.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="scripttask5" id="BPMNShape_scripttask5">
        <omgdc:Bounds height="55.0" width="105.0" x="450.0" y="40.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
        <omgdc:Bounds height="55.0" width="105.0" x="596.0" y="40.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
        <omgdc:Bounds height="55.0" width="105.0" x="596.0" y="130.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
        <omgdi:waypoint x="45.0" y="67.0"></omgdi:waypoint>
        <omgdi:waypoint x="62.0" y="67.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
        <omgdi:waypoint x="167.0" y="67.0"></omgdi:waypoint>
        <omgdi:waypoint x="189.0" y="67.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
        <omgdi:waypoint x="419.0" y="67.0"></omgdi:waypoint>
        <omgdi:waypoint x="450.0" y="67.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
        <omgdi:waypoint x="701.0" y="247.0"></omgdi:waypoint>
        <omgdi:waypoint x="725.0" y="247.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5">
        <omgdi:waypoint x="209.0" y="47.0"></omgdi:waypoint>
        <omgdi:waypoint x="209.0" y="26.0"></omgdi:waypoint>
        <omgdi:waypoint x="284.0" y="26.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6">
        <omgdi:waypoint x="209.0" y="87.0"></omgdi:waypoint>
        <omgdi:waypoint x="209.0" y="108.0"></omgdi:waypoint>
        <omgdi:waypoint x="249.0" y="107.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow7" id="BPMNEdge_flow7">
        <omgdi:waypoint x="354.0" y="107.0"></omgdi:waypoint>
        <omgdi:waypoint x="399.0" y="108.0"></omgdi:waypoint>
        <omgdi:waypoint x="399.0" y="87.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow8" id="BPMNEdge_flow8">
        <omgdi:waypoint x="319.0" y="26.0"></omgdi:waypoint>
        <omgdi:waypoint x="399.0" y="26.0"></omgdi:waypoint>
        <omgdi:waypoint x="399.0" y="47.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow9" id="BPMNEdge_flow9">
        <omgdi:waypoint x="209.0" y="87.0"></omgdi:waypoint>
        <omgdi:waypoint x="209.0" y="187.0"></omgdi:waypoint>
        <omgdi:waypoint x="249.0" y="187.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow10" id="BPMNEdge_flow10">
        <omgdi:waypoint x="354.0" y="187.0"></omgdi:waypoint>
        <omgdi:waypoint x="377.0" y="187.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow11" id="BPMNEdge_flow11">
        <omgdi:waypoint x="397.0" y="167.0"></omgdi:waypoint>
        <omgdi:waypoint x="399.0" y="87.0"></omgdi:waypoint>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="14.0" width="55.0" x="2.0" y="24.0"></omgdc:Bounds>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow12" id="BPMNEdge_flow12">
        <omgdi:waypoint x="397.0" y="207.0"></omgdi:waypoint>
        <omgdi:waypoint x="396.0" y="247.0"></omgdi:waypoint>
        <omgdi:waypoint x="210.0" y="247.0"></omgdi:waypoint>
        <omgdi:waypoint x="210.0" y="188.0"></omgdi:waypoint>
        <omgdi:waypoint x="249.0" y="187.0"></omgdi:waypoint>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="14.0" width="55.0" x="125.0" y="-40.0"></omgdc:Bounds>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow13" id="BPMNEdge_flow13">
        <omgdi:waypoint x="555.0" y="67.0"></omgdi:waypoint>
        <omgdi:waypoint x="596.0" y="67.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow14" id="BPMNEdge_flow14">
        <omgdi:waypoint x="648.0" y="95.0"></omgdi:waypoint>
        <omgdi:waypoint x="648.0" y="130.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow15" id="BPMNEdge_flow15">
        <omgdi:waypoint x="648.0" y="185.0"></omgdi:waypoint>
        <omgdi:waypoint x="648.0" y="220.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

fellowtom
Champ in-the-making
Champ in-the-making
Hi,

I get a little bit further till today (a very little). The problem, that the usertask was performed before the timer fired was my bad. I'm pretty sure now, that it was due to a lack of DB-handling. So the usertask of Worker1 was known to him (from existing DB) and got executed. If I delete DB before, this wont happen again.
But nevertheless the problem exists, that the main java code is executed once while timer is "waiting". After it fires nothing more can happen, because code for usertask was already performed (but without any result because:
taskService.createTaskQuery().taskAssingee("Worker1").list().isEmpty = true
as long as processinstance is dealing with timer [this result was probably "false" with the existing db-problem, so usertask was executed immediatly]).

So I have to check periodically (looping) if the current element is my user task? This is bad performance, isnt it? But how to avoid that the usertask-code is executed meanwhile?
Hope this problem can be solved without listening every moment if my timer has fired.

trademak
Star Contributor
Star Contributor
I read the posts a couple of times, but I really don't understand what you are trying to do and what the issue is . Can you please explain the behavior you would like to see and why you use an intermediate timer event of 10 sec etc. It would also be nice to include a process diagram in the post.

Best regards,

fellowtom
Champ in-the-making
Champ in-the-making
Hi,

Well the process diagramm is not that important, since it has no meaning. I just wanted to try the components first. Well later I want to use the timer for different moments:
- a person needs to be reminded
- a mail need to be sent.
But for testing I dont want to wait longer than a few secs.

Imagine the simple process: Start->Timer->Script->UserTask->End
If I follow the example from the UserGuide, I have to define how the usertask is claimed and completed. This of course after the processEngine was started.
So now: The process is startet and I wait till timer ticks (maybe 10 secs). Then the ScriptTask(just for output) tells me it was handled. Fine. But now, the usertask is not handled. Because its code was already executed after the engine was started. But without results. Of cause –> it was not the current task (so tasklist was empty).

So my question is, if there is a way to:
A: define how tasks are handled maybe before process is started or either
B: some kind of methodinvocation at runtime which dynamically defines the way to execute the current task.

At the moment this is done like: dynamically at wrong time.
I'm sry if I cant explain my problem quite easy/good. I'm pretty new to all this.

trademak
Star Contributor
Star Contributor
Hi,

I just took a look at the process diagram in the Activiti Designer. When the script tasks are completed there are two user tasks defined. When user task 1 is created you should be able to query on it. Activiti doesn't autocomplete user tasks or something like that. So you should get a task back when you do the task query. The only problem I see with your Java code snippet is that it's executed right after the process instance is started. And because the timer has not yet completed the user task is also not yet created.

Best regards,

fellowtom
Champ in-the-making
Champ in-the-making
Hi,

thanks for your reply. Yes thats exactly my problem. The code is executed right after initialisation of processEngine and therefore it is not done when the usertask is reached. My question is how to avoid that behaviour. The engine is not possible to read and interprete the codesnippet for a task before execution begins and then auto-handle it at runtime, isnt it? So my kind of process cant be done like its done in the UserGuide example. Do I need something like a method for each task which is called when that task is reached in process? To change the behaviour to "objectoriented". At the moment my code is more sequential.

Thanks for spending time helping me.

fellowtom
Champ in-the-making
Champ in-the-making
Hi again,…

so to avoid that problem (that usertask is not created but its code is executed before timer triggers) is it a good solution to add the TaskListener to every UserTask?? And then implement the claim and complete methods in that Listener? Should be possible since delegateTask offers that current tasks  Id/Assignee etc.. Is there another way to solve this prob?

With kind regards,
Tom

trademak
Star Contributor
Star Contributor
So this is only for unit testing right?
In our Activiti Engine unit tests we of course face the same issues, so what we do is disable the job executor and first execute the timer job in our unit test. Then you know the job has been executed and you can do the task query. Just take a look around the unit tests in the Activiti Engine project if you need guidance.

Best regards,