cancel
Showing results for 
Search instead for 
Did you mean: 

How can a service task know what task/activity led to its invocation?

brendenr
Champ on-the-rise
Champ on-the-rise

I have a process that involves a series of sensor data incidents which take the form of user tasks to lead to various service tasks being launched. Trouble is the service tasks need to know which incidents caused them to be launched. Simply looking at the history won't work because different incidents may be triggering different service tasks, even simultaneously (or close to). Is there a way for the service task to be passed information related to the previous state(s) that led to it's invocation, or the execution ID's/task ID's that caused it's invocation. Alternatively is there a way for the service task to be able to look back at the previous state(s) somehow to identify which paths led to the invocation so that those tasks could be queried?

1 ACCEPTED ANSWER

brendenr
Champ on-the-rise
Champ on-the-rise

For anyone else doing something similar, here is the solution I've found. I get the sense that this isn't how the API's were intended to be used, but it seems to achieve what I'm looking for. I really wanted a way to get previous tasks without adding bloat to the BPMN diagram itself.

@Service
public class CorrelationService implements JavaDelegate {
   @Override
   public void execute(DelegateExecution execution) throws Exception {
          List<Task> previousTasks = getPreviousTransitionTasks(execution);
   }

   private List<Task> getPreviousTransitionTasks(DelegateExecution execution) {

       // Get incoming transitions
       List<PvmTransition> incomingTransitions = ((ExecutionEntity)execution)
           .getActivity().getIncomingTransitions();

       List<Task> tasks = new ArrayList<Task>();

       for (PvmTransition transition : incomingTransitions) {
           tasks.add(getTaskFromTransition(execution, transition));
       }

       return tasks;
   }

   private Task getTaskFromTransition(DelegateExecution execution, PvmTransition transition) {
       return execution
        .getEngineServices().getTaskService()
        .createTaskQuery()
        .taskId(
            getTaskIdFromTransition(execution, transition)
        ).singleResult();
    }

   private String getTaskIdFromTransition(DelegateExecution execution, PvmTransition transition) {
       return execution
        .getEngineServices().getHistoryService()
        .createHistoricActivityInstanceQuery()
        .activityId(
            ((TransitionImpl) transition).getSource().getId()
        )
        .singleResult()
        .getTaskId();
   }

View answer in original post

3 REPLIES 3

thuynh
Star Contributor
Star Contributor

HI Brenden R ,

There are various approaches to do this.

- Option 1 - Exclusive Gateway: Have a look at the docs here Activiti User Guide . Exclusive gateway allows you to 'choose' what service task to be executed based on the conditions provided by the user task. However, exclusive gateway will allow only and only 1 flow to be executed. If you need more than 1 service task to be executed at a time, we can go to the next option.

- Option 2 - Inclusive GatewayActiviti User Guide . Inclusive gateways allow more service tasks to be executed if the condition-to-execute evaluates to true.

- Option 3 - Event Based GatewayActiviti User Guide . Or you can use event gateway to execute service tasks by intermediate catching event.

- Option 4 - Signals: Have a look at the docs Activiti User Guide . Signal Events allow you implement event subscription/publishing model within the Activiti process. So in your use case, once the user task has completed, it would throw signals e.g. servicetask1-signal, servicetask3-signal. Then you can use the intermediate signal catch event or the signal start event Activiti User Guide to catch them and execute the service tasks as you model. You can place each service task in its own process definition. 

I'm sure one of these approaches should help you. Let me know it does not.

Thanks,

Thong Huynh

gdharley
Elite Collaborator
Elite Collaborator

Brandon,

Interesting scenario you have.

For situations like this I like to add "milestones" to the process model (using none send events and associated listener).
I use these to either update a status or in your case I would add the "status" to an array. As each service task fires, you can feed the array in as a parameter and it will know the key state transitions of the process.

Hope this helps,
Greg

brendenr
Champ on-the-rise
Champ on-the-rise

For anyone else doing something similar, here is the solution I've found. I get the sense that this isn't how the API's were intended to be used, but it seems to achieve what I'm looking for. I really wanted a way to get previous tasks without adding bloat to the BPMN diagram itself.

@Service
public class CorrelationService implements JavaDelegate {
   @Override
   public void execute(DelegateExecution execution) throws Exception {
          List<Task> previousTasks = getPreviousTransitionTasks(execution);
   }

   private List<Task> getPreviousTransitionTasks(DelegateExecution execution) {

       // Get incoming transitions
       List<PvmTransition> incomingTransitions = ((ExecutionEntity)execution)
           .getActivity().getIncomingTransitions();

       List<Task> tasks = new ArrayList<Task>();

       for (PvmTransition transition : incomingTransitions) {
           tasks.add(getTaskFromTransition(execution, transition));
       }

       return tasks;
   }

   private Task getTaskFromTransition(DelegateExecution execution, PvmTransition transition) {
       return execution
        .getEngineServices().getTaskService()
        .createTaskQuery()
        .taskId(
            getTaskIdFromTransition(execution, transition)
        ).singleResult();
    }

   private String getTaskIdFromTransition(DelegateExecution execution, PvmTransition transition) {
       return execution
        .getEngineServices().getHistoryService()
        .createHistoricActivityInstanceQuery()
        .activityId(
            ((TransitionImpl) transition).getSource().getId()
        )
        .singleResult()
        .getTaskId();
   }