cancel
Showing results for 
Search instead for 
Did you mean: 

task.setAssignee() does not affect ACT_HI_ACTINST

naag
Champ in-the-making
Champ in-the-making
Hi all,

it seems that when doing task.setAssignee(), the new assignee is only updated in ACT_RU_TASK and ACT_HI_TASKINST, but not in ACT_HI_ACTINST. This is an excerpt from TaskEntity.java:


  public void setAssignee(String assignee) {
    if (assignee==null && this.assignee==null) {
      return;
    }
    if (assignee!=null && assignee.equals(this.assignee)) {
      return;
    }
    this.assignee = assignee;

    CommandContext commandContext = Context.getCommandContext();
    if (commandContext!=null) {
      commandContext
        .getHistoricTaskInstanceManager()
        .setTaskAssignee(id, assignee);
     
      // if there is no command context, then it means that the user is calling the
      // setAssignee outside a service method.  E.g. while creating a new task.
      if (commandContext!=null) {
        fireEvent(TaskListener.EVENTNAME_ASSIGNMENT);
      }
    }
  }

It's obvious that the HistoricTaskInstance is updated, but why not also the HistoricActivityInstance? Am I doing something wrong? This is happening in a process where the first user task comes right after the process start and has only a candidate set, no assignee. So I claim it manually (via CDI BusinessProcess bean).

Why I need this: I would like to know who made updates to process variables, and since there's no link from ACT_HI_DETAIL to ACT_HI_TASKINST, I have to rely on the information from ACT_HI_ACTINST), see also this thread.

Thanks for your input 🙂

Regards,
Peter
7 REPLIES 7

frederikherema1
Star Contributor
Star Contributor
Peter,

Updated issue, this should indeed be updated. https://jira.codehaus.org/browse/ACT-1248

Just another path you may follow for having rock-solid control of who (and when) an assignee was changed on what task:
   - Add a BPMNParseListener to your engine
   - Have the parse listener add a custom TaskListener to all UserTasks (parseUserTask() method I guess), under the event-name EVENTNAME_ASSIGNMENT = "assignment"
   - In this TaskListener, you can set a task-variable (e.g.. _taskAssignee).
   - Since variable is available in the history, you can order the variable-updates for a certain task by date which shows good trace about updates and their assignee

naag
Champ in-the-making
Champ in-the-making
Hi Frederik,

Thanks for the JIRA update and all your suggestions, it's a really good idea. I will try it now and report back afterwards 🙂

Regards,
Peter

naag
Champ in-the-making
Champ in-the-making
Hi again,

actually I see there's already a UserTaskAssignmentHandler in place by default, which tries to set the assignee on the HistoricActivityInstance. So it should work I guess! But debugging shows me that for the task where I miss the assignee, no CommandContext can be found during TaskEntity.setAssignee(), and that's why no events are fired:


  public void setAssignee(String assignee) {
    // …
    CommandContext commandContext = Context.getCommandContext();
    if (commandContext!=null) {
      // …     
      // if there is no command context, then it means that the user is calling the
      // setAssignee outside a service method.  E.g. while creating a new task.
      if (commandContext!=null) {
        fireEvent(TaskListener.EVENTNAME_ASSIGNMENT);
      }
    }
  }

To give a little bit of context: this is a JSF based application with a listing of user tasks. The user can click a button "Claim" which will go to the CDI bean BusinessProcess.start(taskId, true). I don't know much about Activiti internals, but I would expect that the events are fired in this situation. Or am I wrong somewhere?

Thanks 🙂
Peter

frederikherema1
Star Contributor
Star Contributor
Do you use taskService.setAssignee(taskId, "fred"), because this is the recommended way to do this. In case you are and the assignee is not set on the act-instance, this is still a bug.

naag
Champ in-the-making
Champ in-the-making
Thanks Frederik!

Indeed I was using task.setAssignee(), and not taskService.setAssignee(). Now it's working like expected, so no bug really. I never noticed this in the documentation / book, but maybe I was not paying enough attention.

But it makes me wonder, under which circumstance would I call task.setAssignee()? Or can we say that in general, to correctly modify Activiti entities, we always need to use one of the *Service classes? I was naively expecting that making changes on the entities would work properly.

Tip to everybody else who is like me: study the Activiti Explorer source code, helped me to spot this difference quite easily (sorry, should have done so earlier ;-)).

Regards,
Peter

frederikherema1
Star Contributor
Star Contributor
Actually, now you mention it, task.setAssignee() a valid call IF afterwards, you call taskService.saveTask(task). The SaveTaskCmd will call the setAssignee() and (if updated) will fire the update-event exactly as it does when using taskService.setAssignee(..).

So all activiti-entities returned by the API are actually 'detached' from the engine/persistence.

naag
Champ in-the-making
Champ in-the-making
That's very good to know. Actually TaskService.saveTask() appears several times in the Activiti in Action book, but I never paid attention.

Your statement about everything being detached might be a good addition to the user guide. Especially because under certain circumstances, task.setAssignee() works as expected (surely when somewhere else, you somehow trigger TaskService.saveTask() indirectly during the same transaction).

Anyways, I'm happy now 🙂 Thanks for the great support! I will close the JIRA now.