AnsweredAssumed Answered

NPE when completing task with non-null assignee

Question asked by rhafner on Jul 1, 2013
Latest reply on Jul 7, 2014 by martin.grofcik
I'm hitting a NPE when attempting to complete a task after claiming it with a non-null userId on version 5.13.

Example:
taskService.claim(taskId, "user1");
taskService.complete(taskId);

Digging into the source a bit I see the following comment in GetIdentityLinksForTaskCmd. java suggesting this might be a known issue. However, I was unable to find an issue in JIRA for it.

    // assignee is not part of identity links in the db.
    // so if there is one, we add it here.
    // @Tom: we discussed this long on skype and you agreed ;-)
    // an assignee *is* an identityLink, and so must it be reflected in the API
    //
    // Note: we cant move this code to the TaskEntity (which would be cleaner),
    // since the task.delete cascased to all associated identityLinks
    // and of course this leads to exception while trying to delete a non-existing identityLink

The NPE occurs because GetIdentityLinksForTaskCmd.java creates an ASSIGNEE IdentityLink with a null id when a Task's assignee property is not null. This IdentityLink is then passed to DbSqlSession.delete which performs a sameIdentity() check on the IdentityLink resulting in a NPE on the equals call due to persistentObject.getId() being null.

DbSqlSession.java
    @Override
    public boolean sameIdentity(PersistentObject other) {
      return persistentObject.getClass().equals(other.getClass())
          && persistentObject.getId().equals(other.getId());
    }

Some questions:
1) Has there been any further discussion regarding this issue?
2) Is there a resolution?
3) Any reason null id's can't be considered different for the sameIdentity check?

Including the full StackTrace for reference:

java.lang.NullPointerException
   at org.activiti.engine.impl.db.DbSqlSession$CheckedDeleteOperation.sameIdentity(DbSqlSession.java:209)
   at org.activiti.engine.impl.db.DbSqlSession.delete(DbSqlSession.java:134)
   at org.activiti.engine.impl.persistence.entity.IdentityLinkEntityManager.deleteIdentityLink(IdentityLinkEntityManager.java:31)
   at org.activiti.engine.impl.persistence.entity.IdentityLinkEntityManager.deleteIdentityLinksByProcInstance(IdentityLinkEntityManager.java:89)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.removeIdentityLinks(ExecutionEntity.java:1226)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.remove(ExecutionEntity.java:839)
   at org.activiti.engine.impl.pvm.runtime.AtomicOperationProcessEnd.eventNotificationsCompleted(AtomicOperationProcessEnd.java:62)
   at org.activiti.engine.impl.pvm.runtime.AbstractEventAtomicOperation.execute(AbstractEventAtomicOperation.java:56)
   at org.activiti.engine.impl.interceptor.CommandContext.performOperation(CommandContext.java:87)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:532)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:527)
   at org.activiti.engine.impl.pvm.runtime.AbstractEventAtomicOperation.execute(AbstractEventAtomicOperation.java:49)
   at org.activiti.engine.impl.interceptor.CommandContext.performOperation(CommandContext.java:87)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:532)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:527)
   at org.activiti.engine.impl.pvm.runtime.AtomicOperationActivityEnd.eventNotificationsCompleted(AtomicOperationActivityEnd.java:54)
   at org.activiti.engine.impl.pvm.runtime.AbstractEventAtomicOperation.execute(AbstractEventAtomicOperation.java:56)
   at org.activiti.engine.impl.interceptor.CommandContext.performOperation(CommandContext.java:87)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:532)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:527)
   at org.activiti.engine.impl.pvm.runtime.AbstractEventAtomicOperation.execute(AbstractEventAtomicOperation.java:49)
   at org.activiti.engine.impl.interceptor.CommandContext.performOperation(CommandContext.java:87)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:532)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:527)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.end(ExecutionEntity.java:340)
   at org.activiti.engine.impl.bpmn.behavior.NoneEndEventActivityBehavior.execute(NoneEndEventActivityBehavior.java:24)
   at org.activiti.engine.impl.pvm.runtime.AtomicOperationActivityExecute.execute(AtomicOperationActivityExecute.java:44)
   at org.activiti.engine.impl.interceptor.CommandContext.performOperation(CommandContext.java:87)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:532)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:527)
   at org.activiti.engine.impl.pvm.runtime.AtomicOperationTransitionNotifyListenerStart.eventNotificationsCompleted(AtomicOperationTransitionNotifyListenerStart.java:52)
   at org.activiti.engine.impl.pvm.runtime.AbstractEventAtomicOperation.execute(AbstractEventAtomicOperation.java:56)
   at org.activiti.engine.impl.interceptor.CommandContext.performOperation(CommandContext.java:87)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:532)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:527)
   at org.activiti.engine.impl.pvm.runtime.AbstractEventAtomicOperation.execute(AbstractEventAtomicOperation.java:49)
   at org.activiti.engine.impl.interceptor.CommandContext.performOperation(CommandContext.java:87)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:532)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:527)
   at org.activiti.engine.impl.pvm.runtime.AtomicOperationTransitionCreateScope.execute(AtomicOperationTransitionCreateScope.java:49)
   at org.activiti.engine.impl.interceptor.CommandContext.performOperation(CommandContext.java:87)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:532)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:527)
   at org.activiti.engine.impl.pvm.runtime.AtomicOperationTransitionNotifyListenerTake.execute(AtomicOperationTransitionNotifyListenerTake.java:66)
   at org.activiti.engine.impl.interceptor.CommandContext.performOperation(CommandContext.java:87)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:532)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:527)
   at org.activiti.engine.impl.pvm.runtime.AtomicOperationTransitionDestroyScope.execute(AtomicOperationTransitionDestroyScope.java:116)
   at org.activiti.engine.impl.interceptor.CommandContext.performOperation(CommandContext.java:87)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:532)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:527)
   at org.activiti.engine.impl.pvm.runtime.AtomicOperationTransitionNotifyListenerEnd.eventNotificationsCompleted(AtomicOperationTransitionNotifyListenerEnd.java:36)
   at org.activiti.engine.impl.pvm.runtime.AbstractEventAtomicOperation.execute(AbstractEventAtomicOperation.java:56)
   at org.activiti.engine.impl.interceptor.CommandContext.performOperation(CommandContext.java:87)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:532)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:527)
   at org.activiti.engine.impl.pvm.runtime.AbstractEventAtomicOperation.execute(AbstractEventAtomicOperation.java:49)
   at org.activiti.engine.impl.interceptor.CommandContext.performOperation(CommandContext.java:87)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:532)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:527)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.take(ExecutionEntity.java:367)
   at org.activiti.engine.impl.bpmn.behavior.BpmnActivityBehavior.performOutgoingBehavior(BpmnActivityBehavior.java:105)
   at org.activiti.engine.impl.bpmn.behavior.BpmnActivityBehavior.performDefaultOutgoingBehavior(BpmnActivityBehavior.java:54)
   at org.activiti.engine.impl.bpmn.behavior.FlowNodeActivityBehavior.leave(FlowNodeActivityBehavior.java:44)
   at org.activiti.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior.leave(AbstractBpmnActivityBehavior.java:47)
   at org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior.signal(UserTaskActivityBehavior.java:96)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.signal(ExecutionEntity.java:350)
   at org.activiti.engine.impl.persistence.entity.TaskEntity.complete(TaskEntity.java:160)
   at org.activiti.engine.impl.cmd.CompleteTaskCmd.execute(CompleteTaskCmd.java:39)
   at org.activiti.engine.impl.cmd.CompleteTaskCmd.execute(CompleteTaskCmd.java:24)
   at org.activiti.engine.impl.cmd.NeedsActiveTaskCmd.execute(NeedsActiveTaskCmd.java:61)
   at org.activiti.engine.impl.interceptor.CommandExecutorImpl.execute(CommandExecutorImpl.java:24)
   at org.activiti.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:61)
   at org.activiti.spring.SpringTransactionInterceptor$1.doInTransaction(SpringTransactionInterceptor.java:42)
   at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130)
   at org.activiti.spring.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:40)
   at org.activiti.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:31)
   at org.activiti.engine.impl.TaskServiceImpl.complete(TaskServiceImpl.java:163)

Outcomes