cancel
Showing results for 
Search instead for 
Did you mean: 

Get All Active Tasks, Including Sub Process Tasks

mikebrown01
Champ in-the-making
Champ in-the-making
Hi.

Is there a way to get all active tasks including those from a subprocess (invoked using Call Activity)?

I've tried the following
1) List<Task> tasks = taskService.createTaskQuery().executionId(processInstanceId).list();
– Only gives tasks for specified process

2) Passing in Business Key
– That doesnt get passed down to the sub processes

3) Get the process Id for launched sub processes
– Can't see a way to do it.

4) Investigated using taskService.createNativeQuery()
– Don't see in the tables how to generate a query that will allow me to get all of the tasks….which
is probably a bad sign Smiley Sad

9 REPLIES 9

trademak
Star Contributor
Star Contributor
Maybe you could set a specific process variable in the parent and sub processes that enables you to query on them?

Best regards,

Hi, I need to query for all the active user tasks including from Sub process (Call Activity). When I query the task service using process Instance Id, I get only parent process user tasks. How to achieve that? , We tried above one and it doesnt seem to be work.

mikebrown01
Champ in-the-making
Champ in-the-making

Tijs,

From reading forum posts I am trying to do exactly as you suggested. However, I can't get it to work.
In addition, there are probably 4-5 posts where people ask the same question but there is no working solution given.

Here is what I have so far.

1) Created a Listener (type=Java class) on the Start event of my subProcess invoked through CallActivity from the parent.
2) In that Listener I am unable to get the parent process in order to get the parent process's variables.

The following calls all return null.  So I can't get past the first step which is getting the parent.

<code>
public void notify(DelegateExecution exec) throws Exception {

   String superExecutionId = executionEntity.getSuperExecutionId();  // This works.

   Execution e1 = exec.getEngineServices().getRuntimeService().createProcessInstanceQuery().processInstanceId  (superExecutionId).singleResult();

   Execution e2 = exec.getEngineServices().getRuntimeService().createProcessInstanceQuery().superProcessInstanceId(superExecutionId).singleResult();

  Execution e3 = exec.getEngineServices().getRuntimeService().createExecutionQuery().processInstanceId(superExecutionId).singleResult();
 

}
</code>

Can you please actually try this and see if you can get it to work?

Regards,
Mike

mikebrown01
Champ in-the-making
Champ in-the-making
Nevermind, I got it.  The problem was, querries can not be used because the business processes are not yet in the db.

Here is the code I have that reads the business key from the top level process and adds it as a process variable.
For a subprocess it reads the variable from the calling process and sets it for the sub process.

To make this work you invoke the following event handler for Start event for the main flow and all subflows.

<code>
public class BusinessKeyInjectionListener implements ExecutionListener {

/**
  *
  */
private static final long serialVersionUID = 1L;

@Override
public void notify(DelegateExecution exec) throws Exception {
 
  System.out.println("In BusinessKey Injection Listener");
 
  ExecutionEntity thisEntity = (ExecutionEntity)exec;
  ExecutionEntity superExecEntity = thisEntity.getSuperExecution();
 
  String key = "";
 
  // Check if this is the main process.
  if( superExecEntity == null ){
 
                                      // If it is, get the business key the main process was launched with.
         key = thisEntity.getBusinessKey();
     
   
  }else{
  
                        // We are a subprocess so get the BusinessKey variable set by the caller.
                        // This should work for N level deep sub processes.
                        key = (String)superExecEntity.getVariable("BusinessKey");
  
  }
 
  // Set a process variable with the business key. Can't actually set business key because business keys
  // have to be unique per process instance.
  thisEntity.setVariable("BusinessKey", key);
  
}

}


</code>


Then to get all active Tasks for the parent or any sub flows you can easily query for them using

<code>
List<Task> tasks = taskService.createTaskQuery().processVariableValueEquals("BusinessKey", businessKey ).list();
</code>

raka
Champ in-the-making
Champ in-the-making

alexsinyushkin
Champ in-the-making
Champ in-the-making
Hi,
We had the same problem in our project. We solved it in a bit different way. We use Activiti as a process orchestrator.  And we use org.activiti.engine.delegate.event.ActivitiEventListener set up as a bean in Spring application context. In its onEvent(ActivitiEvent event) method we analyse event type and when a process creates a user task it issues a TASK_CREATED event. What we found out is that if you are looking into an event which was created in a sub process launched via an activity call, its execution entity will have a super execution entity which we can iterate through up to the top to get the parent process instance id. Then we set task entity this process instance id as an assignee:
<java>
    @Override
    public void onEvent(ActivitiEvent event) {
        switch (event.getType()) {
        case TASK_CREATED:
            ActivitiEntityEvent activityEntityEvent = (ActivitiEntityEvent) event;
            TaskEntity taskEntity = (TaskEntity) activityEntityEvent.getEntity();
            ExecutionEntity exEntity = taskEntity.getExecution();
            String superExId = getSuperProcessInstanceId(exEntity != null ? exEntity.getSuperExecution() : null);

            if (superExId != null) {
                taskEntity.setAssignee(superExId);
            }
            break;
            ….
    }

    private String getSuperProcessInstanceId(ExecutionEntity exEntity) {
        if (exEntity != null && exEntity.getSuperExecution() != null) {
            return getSuperProcessInstanceId(exEntity.getSuperExecution());
        } else if (exEntity != null) {
            return exEntity.getProcessInstanceId();
        }
       
        return null;
    }

</java>

And then, at the place where we need to get all user tasks created within process and all its sub processes, we just query by process instance id and by assignee using the same process instance id as the assignee id:

<java>
import org.activiti.engine.TaskService;



    List<Task> userTasksByProcessInstanceId = taskService.createTaskQuery().processInstanceId(processId).list();
    List<Task> tasksByAssignee = taskService.createTaskQuery().taskAssignee(processId).list();
    //now merge both lists into a single one    
</java>

So, this way we are sure we'll get only those sub processes' user tasks which are created by our main process since the process instance id is unique. Also, we do not have to add any event listeners to any of the elements inside the workflow as the entire mechanism is transparent to the developers who create diagrams.

jbarrez
Star Contributor
Star Contributor
Thanks for sharing your solution!

dmeilinger
Champ in-the-making
Champ in-the-making
Thanks for the suggested solutions, I was able to get a variant of this working today in an EventListener.  I wasn't able to determine which type of entity was being created, if anyone has a suggestion for that (instead of just swallowing the cast exception) I would much rather do that 😃

<java>
case ENTITY_CREATED:
   entityEvent = (ActivitiEntityEvent)event;
   try {
    @SuppressWarnings("null")
    ExecutionEntity executionEntity = (ExecutionEntity)entityEvent.getEntity();
   
    ExecutionEntity superExecEntity = executionEntity.getSuperExecution(); 
    String key = "";
    
    // Check if this is the main process.
    if( superExecEntity == null ){
     //key = executionEntity.getBusinessKey();
     key = (String) executionEntity.getVariable("propertyID");
    }else{
     key = (String)superExecEntity.getVariable("propertyID");
    }

    executionEntity.setVariable("propertyID", key);

   } catch (Exception e) {
    //System.out.println("ENTITY CAST ERROR !!!!!!!!");
   }
</java>   

jbarrez
Star Contributor
Star Contributor
Why not having an instanceof check first?