cancel
Showing results for 
Search instead for 
Did you mean: 

Completing a Task from within a CreateListener?

ankhara33
Champ in-the-making
Champ in-the-making
I have a special situation where in some cases, when a UserTask is created, I want to 'automatically' complete it – but I still need to do some work, such as log that it was automatically created and approved. When I call getTaskService().completeTask(id) from inside the TaskListener, I get an exception about the Task not being found – it appears the TaskListener on the 'create' event is called prior to the Task actually being saved?

Is there any way to do this? I'm working with a DelegateTask inside the TaskListener.notify() method.

Thanks,
Sheila.
17 REPLIES 17

t5d
Champ in-the-making
Champ in-the-making
Hello, Frederik. Thank you for your response.

I understand, that this logic is not within design of Activiti.
Having exclusive gateways in front of every task is too expensive and uncontrollable, as we have dozens of tasks.

Following your logic: I should post some message from create listener to some external layer, so that it finds out that the task should be closed. I think that after-commit listener (post #7) is much like this, but it confuses external transaction somehow.

How would you design the external layer, that should complete the task automatically and post message to it?

frederikherema1
Star Contributor
Star Contributor
No, I mean in the place where you call the activiti API that could potentially cause such a task to be created. After calling the appropriate method on Activiti API (e.g. startProcessByKey()), you can query for tasks in the process that should be auto-completed due to some condition being true. If such tasks are found, complete them using the taskService. Ideally, having transaction-manager setup so that transactions span both API-calls (e.g. using spring transaction manager).

However, Tijs told me that completing the task from within the listener should work (in case no special conditions are true, like a multi-instance task). Is it a create or assignment-listener? Perhaps it works with more recent versions of Activiti.

t5d
Champ in-the-making
Champ in-the-making
The calls to Activiti are made in Alfresco code, however, there are some hook points like form filters, I should try this variant.

My listener is a create listener. As far as I understood Activiti manual, assignment-listener can be called before it to set task assignee, so I used create listener.
First two tasks (on which I check this behaviour) are connected sequentally, no multi-instance, nothing special…
Perhaps, newer version allows to complete task from listener, I can check this process in latest Alfresco 4.2.c with Activiti 5.10.

Another question:
When in listener, the code is executed from wrapped LogInterceptor, SpringTransactionInterceptor, CommandContextInterceptor.
When I call TaskService method from listener its code is also wrapped in this interceptors - i.e. another transaction will be opened.
Wouldn't this cause any transaction-related problems?

frederikherema1
Star Contributor
Star Contributor
If I'm not mistaken, the transaction will be reused, as a transaction-context is active already… As of 5.13, activiti offers access to the Services through the DelegateTask, ensuring correct transaction handling. But due to the integration in alfresco, the shared transaction manager will make sure the same transaction is used (unless a REQUIRES_NEW is explicit ally required, by e.g.? failing job-executor).

t5d
Champ in-the-making
Champ in-the-making
Hello, Frederik.

Finally, I succeeded with your way - call TaskService.complete() after calls to other Activiti code.
To be precise - I did this in Alfresco form filter in afterPersist method.

Thank you for your advice.

dineshwijesingh
Champ in-the-making
Champ in-the-making
dear t5d

i have a same issue and need you support to solve this.
please let me know how you implement TaskService.complete() methout to auto complete a task

lmazurk
Champ in-the-making
Champ in-the-making
My piece of code - it works form at least:


@Service
public class CustomListener  implements ActivitiEventListener {
        @Override
public void onEvent(ActivitiEvent event) {
         switch (event.getType()){
         case TASK_CREATED:
   onTaskCreated((ActivitiEntityEventImpl) event);
   break;        
         }

private void onTaskCreated(ActivitiEntityEventImpl event) {
  TaskEntity task=(TaskEntity) event.getEntity();
 
  String decision=procS.getLastDecision(event.getExecutionId());
  if(decision!=null && decision.equals(StatusType.REJECTED)){
   task.complete(null, true);
  }
  else{
   serviceUserTask.setDefultAssignee(task);
  }
}

}

Hello Imazurk,

I am trying to complete the user task automatically with ActivitiEventListener, as you did. Task is getting completed, but when it moves to next task throwing persistence exception:

### Error updating database.  Cause: org.postgresql.util.PSQLException: ERROR: insert or update on table "act_ru_identitylink" violates foreign key constraint "act_fk_tskass_task"
18:47:41,755 INFO  [stdout] (http-localhost/127.0.0.1:8080-1)   Detail: Key (task_id_)=(207521) is not present in table "act_ru_task".

Can you please help me on this?

Thanks in advance.