Reassigning & Task Complete race problem

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-26-2015 09:20 AM
i opened two browers. opened same user task on both browsers. Now did task "reassign" from one browser. and after that task "complete" from another browser. since i reassigned task before clicking on "complete" i expected some kind of error. but no error came. Now as per task service documentation,
void complete(String taskId);
throws only two exceptions…: /*@throws ActivitiObjectNotFoundException when no task exists with the given id. * @throws ActivitiException when this task is {@link DelegationState#PENDING} delegation. */ void complete(String taskId);
Now task exists with the given id so no exception was thrown.
My question 1: how can i prevent same situation from appearing in my own application? I have a supervisor who can reassign tasks huge number of tasks.
But if a user has already opened a task, and is working on it, i dont want supervisor to do a reassign on it. (OR) if a supervisor reassigns a task, the origin user should not be able to complete the task.
question 2: How can i achieve this?
- Labels:
-
Archive

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-26-2015 10:39 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-31-2015 04:20 AM
No. When the task is assigned, it is supposed to be done by that user.
In your application, you should add a check before doing the complete call. This is not done in Explorer, but could be added easily to your own application.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-31-2015 08:27 AM
<blockcode>
if ( taskService.createTaskQuery().taskAssignee(assignee).taskId(taskId).singleResult() != null )
{
taskService.complete(taskId, taskVariables);
}
</blockcode>
But i will have to put it inside a synchronized block to prevent another thread (supervisor working on another browser) from reassigning after the execution of the "if" statement.
so i will have to change it as
<blockcode>
synchronized(this){
if ( taskService.createTaskQuery().taskAssignee(assignee).taskId(taskId).singleResult() != null )
{
taskService.complete(taskId, taskVariables);
}
}
</blockcode>
Similarly i will have to put all the code below run by a supervisor in synchronized block.
<blockcode>
//delink all tasks linked with this queue id.
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup(queueId)
.includeTaskLocalVariables().includeProcessVariables()
.orderByTaskId().desc().list();
logger.info("total tasks in "+queueId+"is:"+tasks.size());
for(Task task : tasks){
// Update assignee
String originAssignee = task.getAssignee();
logger.info("originAssignee:"+originAssignee+":created time:"+task.getCreateTime());
taskService.deleteCandidateGroup(task.getId(), queueId);
// reassign to another user…
task.setAssignee("kermit");
}
</blockcode>
Using synchronized on these statements, Will this affect the performance ? ?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-07-2015 08:21 AM
Activiti is designed to cope with this: the taskquery goes to the database and will return null if the task is already fetched by someone else. So you need nothing else and don't need to worry about performance.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-10-2015 05:45 AM
The scenario where i feel it will fail is below:
User thread:
=======
<code>
(1)if ( taskService.createTaskQuery().taskAssignee(assignee).taskId(taskId).singleResult() != null )
{
(2) taskService.complete(taskId, taskVariables);
}
</code>
Supervisor thread:
===========
<code>
//reassign user
(3) TaskService().setAssignee(task.getId(), selectedUser));
</code>
if after execution of (1), (3) executes (they are running indifferent threads,) then (2) executes, then there will be problem.
if sequence of execution is (1),(3),(2) then there will be problem. Hence i have to use synchronised.
Am i wrong in saying to?
Please suggest.
Thanks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-14-2015 08:23 AM

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-16-2015 09:19 AM
The javadoc for setAssignee only states the below from which i cannot infer what you state. Seems i have to dive deep into code..
"Changes the assignee of the given task to the given userId. No check is done whether the user is known by the identity component.
Parameters:
taskId id of the task, cannot be null.
userId id of the user to use as assignee.
Throws:
ActivitiObjectNotFoundException - when the task or user doesn't exist".
From this , i inferred that exception will be thrown only when task/user doesn't exist.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-21-2015 04:08 AM

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-21-2015 08:10 AM
That's why i suggested using <code>synchronized</code>
