Uploaded image for project: 'camunda BPM'
  1. camunda BPM
  2. CAM-8494

NullPointerException when calling TaskService#getIdentityLinksForTask in TaskListener on complete

XMLWordPrintable

      Forum post: https://forum.camunda.org/t/nullpointerexception-while-completing-a-task/5454

      Hi,

      we are trying to switch to camunda 7.8 but we are facing a NPE while trying to complete a UserTask via REST-API. The reason why this happens is rather curious:

      We registered a taskNotificationListener which sends notifications via websockets when a task gets completed (via taskService.getIdentityLinksForTask(delegateTask.getId())). This method uses the GetIdentityLinksForTaskCmd which programmatically adds a new IdentityLinkObject to the IdentityList. Thankfully the comment in this method already explains the NPE. Camunda then tries to complete and delete this task with all associated Identitylinks (TaskManager:L84). Since everything happens in the same thread, the TaskEntity is already cached in dbEntityCache AND the (dirty) List with IdentityLinkEntities is already loaded. An IdentityLinkEntity with ID [NULL] gets passed to the DbOperationsManager and the underlying DbEntityOperationComparator where it goes Boom. I’ve added the relevant code and the stacktrace below…

      the execute method in GetIdentityLinksForTaskCmd loads the IdentityLinks and adds a new Entity with ID [NULL] to the List.

          List<IdentityLink> identityLinks = (List) task.getIdentityLinks();
      
          // 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
          if (task.getAssignee() != null) {
            IdentityLinkEntity identityLink = new IdentityLinkEntity();
            identityLink.setUserId(task.getAssignee());
            identityLink.setTask(task);
            identityLink.setType(IdentityLinkType.ASSIGNEE);
            identityLinks.add(identityLink);
          }
          if (task.getOwner() != null) {
            IdentityLinkEntity identityLink = new IdentityLinkEntity();
            identityLink.setUserId(task.getOwner());
            identityLink.setTask(task);
            identityLink.setType(IdentityLinkType.OWNER);
            identityLinks.add(identityLink);
          }
      
          return (List) task.getIdentityLinks();
      

      TaskEntity.getIdentityLinks() does not reload its IdentityLinks once initalized, so the dirty IdentityLinkEntity stays in the List

      public List<IdentityLinkEntity> getIdentityLinks() {
          if (!isIdentityLinksInitialized) {
            taskIdentityLinkEntities = Context
              .getCommandContext()
              .getIdentityLinkManager()
              .findIdentityLinksByTaskId(id);
            isIdentityLinksInitialized = true;
          }
      
          return taskIdentityLinkEntities;
        }
      

      NPE-Stacktrace

      Caused by: java.lang.NullPointerException: null
      	at java.lang.String.compareTo(String.java:1155) ~[na:1.8.0_74]
      	at org.camunda.bpm.engine.impl.db.entitymanager.operation.comparator.DbEntityOperationComparator.compare(DbEntityOperationComparator.java:35) ~[camunda-engine-7.8.0.jar:7.8.0]
      	at org.camunda.bpm.engine.impl.db.entitymanager.operation.comparator.DbEntityOperationComparator.compare(DbEntityOperationComparator.java:24) ~[camunda-engine-7.8.0.jar:7.8.0]
      	at java.util.TreeMap.put(TreeMap.java:552) ~[na:1.8.0_74]
      	at java.util.TreeSet.add(TreeSet.java:255) ~[na:1.8.0_74]
      	at org.camunda.bpm.engine.impl.db.entitymanager.operation.DbOperationManager.addOperation(DbOperationManager.java:75) ~[camunda-engine-7.8.0.jar:7.8.0]
      	at org.camunda.bpm.engine.impl.db.entitymanager.DbEntityManager.performEntityOperation(DbEntityManager.java:572) ~[camunda-engine-7.8.0.jar:7.8.0]
      	at org.camunda.bpm.engine.impl.db.entitymanager.DbEntityManager.flushCachedEntity(DbEntityManager.java:451) ~[camunda-engine-7.8.0.jar:7.8.0]
      	at org.camunda.bpm.engine.impl.db.entitymanager.DbEntityManager.flushEntityCache(DbEntityManager.java:417) ~[camunda-engine-7.8.0.jar:7.8.0]
      	at org.camunda.bpm.engine.impl.db.entitymanager.DbEntityManager.flush(DbEntityManager.java:283) ~[camunda-engine-7.8.0.jar:7.8.0]
      	at org.camunda.bpm.engine.impl.interceptor.CommandContext.flushSessions(CommandContext.java:203) ~[camunda-engine-7.8.0.jar:7.8.0]
      	at org.camunda.bpm.engine.impl.interceptor.CommandContext.close(CommandContext.java:132) ~[camunda-engine-7.8.0.jar:7.8.0]
      	at org.camunda.bpm.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:113) ~[camunda-engine-7.8.0.jar:7.8.0]
      	at org.camunda.bpm.engine.spring.SpringTransactionInterceptor$1.doInTransaction(SpringTransactionInterceptor.java:42) ~[camunda-engine-spring-7.8.0.jar:7.8.0]
      	at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133) ~[spring-tx-4.3.12.RELEASE.jar:4.3.12.RELEASE]
      	at org.camunda.bpm.engine.spring.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:40) ~[camunda-engine-spring-7.8.0.jar:7.8.0]
      	at org.camunda.bpm.engine.impl.interceptor.ProcessApplicationContextInterceptor.execute(ProcessApplicationContextInterceptor.java:66) ~[camunda-engine-7.8.0.jar:7.8.0]
      	at org.camunda.bpm.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:30) ~[camunda-engine-7.8.0.jar:7.8.0]
      	at org.camunda.bpm.engine.impl.TaskServiceImpl.complete(TaskServiceImpl.java:173) ~[camunda-engine-7.8.0.jar:7.8.0]
      	at org.camunda.bpm.engine.rest.sub.task.impl.TaskResourceImpl.complete(TaskResourceImpl.java:96) ~[camunda-engine-rest-core-7.8.0.jar:7.8.0]
      	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_74]
      	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_74]
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_74]
      	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_74]
      

      A solution for this issue would be returning a copy of List<IdentityLinkEntity> with the dirty entity in the GetIdentityForTaskCmd.

      Cheers,
      Jürgen

        This is the controller panel for Smart Panels app

              Unassigned Unassigned
              derfritz Jürgen Fritz
              Yana Vasileva Yana Vasileva
              Daniel Kelemen Daniel Kelemen
              Votes:
              4 Vote for this issue
              Watchers:
              7 Start watching this issue

                Created:
                Updated:
                Resolved: