cancel
Showing results for 
Search instead for 
Did you mean: 

User task, ExecutionId and Timer Boundary Event

jackw
Champ in-the-making
Champ in-the-making
When the Timer Boundary Event is attached to the User Task, this task is created with executionId of "subprocess".
This suprocess probably handles branche of attached timer. But I think the user task should belongs (executionId) to main process instead of subprocess.

I have scenario with user task with recurrent mail notification. I use cancelActivity="false" since I want to user task remain after trigger fires and sends email (it is only notification).

Is this correct behaviour? Why?
6 REPLIES 6

jackw
Champ in-the-making
Champ in-the-making
I try to be more specific.

Process:

<process id="Proces1" name="proces1">
    <startEvent id="startevent1" name="Start"></startEvent>
    <userTask id="usertask1" name="User Form" activiti:assignee="none" activiti:formKey="FORM">
      <documentation>User form</documentation>
    </userTask>
    <endEvent id="endevent1" name="End"></endEvent>
    <boundaryEvent id="boundarytimer1" name="Timer" cancelActivity="true" attachedToRef="usertask1">
      <timerEventDefinition>
        <timeDuration>PT1H</timeDuration>
      </timerEventDefinition>
    </boundaryEvent>
    <serviceTask id="servicetask1" name="Mail Notification" activiti:expression="${mailto}"></serviceTask>
    <endEvent id="endevent2" name="End"></endEvent>
    <sequenceFlow id="flow1" name="" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
    <sequenceFlow id="flow2" name="" sourceRef="usertask1" targetRef="endevent1"></sequenceFlow>
    <sequenceFlow id="flow3" name="" sourceRef="servicetask1" targetRef="endevent2"></sequenceFlow>
    <sequenceFlow id="flow4" name="" sourceRef="boundarytimer1" targetRef="servicetask1"></sequenceFlow>
  </process>

Test:

public void testExecutionIdWithBoundaryEvent() {
runtimeService.startProcessInstanceByKey("Proces1");
List<Execution> list = runtimeService.createExecutionQuery().list();
Execution mainExecution = list.get(0);
Execution boundaryExecution = list.get(1);
// Why user task is created under boundaryExecution.id
// assertNotNull(taskService.createTaskQuery()
//  .executionId(mainExecution.getId()).singleResult());
assertNotNull(taskService.createTaskQuery()
   .executionId(boundaryExecution.getId()).singleResult());
}

jackw
Champ in-the-making
Champ in-the-making
Sorry, It should be cancelActivity="false" in a process definition.

frederikherema1
Star Contributor
Star Contributor
Does this mean your problem is solved?

The seperate execution on the task with a boundry timer on it is indeed the correct behaviour, this is the way activiti handles this.

jackw
Champ in-the-making
Champ in-the-making
Sorry, still not clear. Yes I understand that there is new separate execution under the boundary event, but usertask1 should belongs to the main execution logically. Since cancelActivity="false" means "not remove main execution".
But in database, usertask1 is created as it belongs to boundary execution.

The problem is that it is not possible to render active task for executionId.
Of course, You can use processInstanceId, but it is still quite messy for me.

frederikherema1
Star Contributor
Star Contributor
It actually is "logically" part of the execution, using a child-execution Smiley Wink But I get the issue, since it's not trivial to find the user-task on the execution.

As I said, this extra execution is added for internal reasons (creating a scope, to prevent concurrency problems when timer fires and task is completed etc). So it's not likely this will disappear.

Maybe it would make sense to introduce a method on the TaskQuery like executionIdOrParentExecutionId(execution.getId()) to overcome this issue or even a query that gives all tasks that are part of ANY execution that is a child of (or the parent itself) the execution with the given Id (not only first level child). Just thinking out loud, but in this usecase it will definitely make sense….

jackw
Champ in-the-making
Champ in-the-making
Ok, Thank you. With concurrency it makes sense.

As I wrote, it is possible to use processInstanceId, but imho it is overhead to remember two IDs (executionId, processInstanceId) to query userTasks in one database hit. So such extension you mention above would be handy.
Maybe also for reducing database traffic.