NPE while assigning candidate users in process instance

I have a process model with 2 process roles.

All the user tasks have one or 2 of these roles as candidategroups.

I start the process instance programmatically as below but get an NPE because the userId on the IdentityLinkEntity is null.
I’m quite sure I\m doing something right, but where?

Edit: I just tried assigning users through the BPM screens and starting the application. the same problem arises.

@Override
public void startInvoiceBpm(Invoice invoice) {
    BpmEntitiesService.ProcInstanceDetails procInstanceDetails = new BpmEntitiesService.ProcInstanceDetails(PROCESS_CODE);

    ProcDefinition procDefinition = bpmRepository.findProcessDefinition(BusinessFlow.InvoiceFlow);
    List<ProcRole> roles = procDefinition.getProcRoles();

    roles.forEach(r -> {
        BusinessRole businessRole = userService.getBusinessRole(r.getName());
        userService.getUsersForBusinessRoles(Collections.singletonList(businessRole)).forEach(u -> procInstanceDetails.addProcActor(r, u));
    });
    procInstanceDetails.setEntity(invoice);
    ProcInstance procInstance = bpmEntitiesService.createProcInstance(procInstanceDetails);
    processRuntimeService.startProcess(procInstance, "Process started programmatically", new HashMap<>());
}

Exception:

    java.lang.NullPointerException
        at java.util.UUID.fromString(UUID.java:192)
        at com.haulmont.bpm.core.ProcessRuntimeManagerBean.getCandidateUsers(ProcessRuntimeManagerBean.java:435)
        at com.haulmont.bpm.core.ProcessRuntimeManagerBean.createNotAssignedProcTask(ProcessRuntimeManagerBean.java:377)
        at com.haulmont.bpm.core.engine.listener.BpmActivitiListener.onEvent(BpmActivitiListener.java:72)
        at org.activiti.engine.impl.bpmn.helper.DelegateActivitiEventListener.onEvent(DelegateActivitiEventListener.java:45)
        at org.activiti.engine.delegate.event.impl.ActivitiEventSupport.dispatchEvent(ActivitiEventSupport.java:105)
        at org.activiti.engine.delegate.event.impl.ActivitiEventSupport.dispatchEvent(ActivitiEventSupport.java:98)
        at org.activiti.engine.delegate.event.impl.ActivitiEventDispatcherImpl.dispatchEvent(ActivitiEventDispatcherImpl.java:74)
        at org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior.execute(UserTaskActivityBehavior.java:209)
        at org.activiti.engine.impl.pvm.runtime.AtomicOperationActivityExecute.execute(AtomicOperationActivityExecute.java:60)
        at org.activiti.engine.impl.interceptor.CommandContext.performOperation(CommandContext.java:97)
        at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:636)
        at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:629)
        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:97)
        at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:636)
        at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:629)
        at org.activiti.engine.impl.pvm.runtime.AbstractEventAtomicOperation.execute(AbstractEventAtomicOperation.java:49)
        at org.activiti.engine.impl.interceptor.CommandContext.performOperation(CommandContext.java:97)
        at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:636)
        at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:629)
        at org.activiti.engine.impl.pvm.runtime.AtomicOperationTransitionCreateScope.execute(AtomicOperationTransitionCreateScope.java:49)
        at org.activiti.engine.impl.interceptor.CommandContext.performOperation(CommandContext.java:97)
        at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:636)
        at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:629)
        at org.activiti.engine.impl.pvm.runtime.AtomicOperationTransitionNotifyListenerTake.execute(AtomicOperationTransitionNotifyListenerTake.java:80)
        at org.activiti.engine.impl.interceptor.CommandContext.performOperation(CommandContext.java:97)
        at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:636)
        at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:629)
        at org.activiti.engine.impl.pvm.runtime.AtomicOperationTransitionDestroyScope.execute(AtomicOperationTransitionDestroyScope.java:116)
        at org.activiti.engine.impl.interceptor.CommandContext.performOperation(CommandContext.java:97)
        at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:636)
        at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:629)
        at org.activiti.engine.impl.pvm.runtime.AtomicOperationTransitionNotifyListenerEnd.eventNotificationsCompleted(AtomicOperationTransitionNotifyListenerEnd.java:35)
        at org.activiti.engine.impl.pvm.runtime.AbstractEventAtomicOperation.execute(AbstractEventAtomicOperation.java:56)
        at org.activiti.engine.impl.interceptor.CommandContext.performOperation(CommandContext.java:97)
        at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:636)
        at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:629)
        at org.activiti.engine.impl.pvm.runtime.AbstractEventAtomicOperation.execute(AbstractEventAtomicOperation.java:49)
        at org.activiti.engine.impl.interceptor.CommandContext.performOperation(CommandContext.java:97)
        at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:636)
        at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:629)
        at org.activiti.engine.impl.persistence.entity.ExecutionEntity.take(ExecutionEntity.java:453)
        at org.activiti.engine.impl.persistence.entity.ExecutionEntity.take(ExecutionEntity.java:431)
        at org.activiti.engine.impl.bpmn.behavior.BpmnActivityBehavior.performOutgoingBehavior(BpmnActivityBehavior.java:140)
        at org.activiti.engine.impl.bpmn.behavior.BpmnActivityBehavior.performDefaultOutgoingBehavior(BpmnActivityBehavior.java:66)
        at org.activiti.engine.impl.bpmn.behavior.FlowNodeActivityBehavior.leave(FlowNodeActivityBehavior.java:44)
        at org.activiti.engine.impl.bpmn.behavior.FlowNodeActivityBehavior.execute(FlowNodeActivityBehavior.java:36)
        at org.activiti.engine.impl.pvm.runtime.AtomicOperationActivityExecute.execute(AtomicOperationActivityExecute.java:60)
        at org.activiti.engine.impl.interceptor.CommandContext.performOperation(CommandContext.java:97)
        at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:636)
        at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:629)
        at org.activiti.engine.impl.pvm.runtime.AtomicOperationProcessStartInitial.eventNotificationsCompleted(AtomicOperationProcessStartInitial.java:45)
        at org.activiti.engine.impl.pvm.runtime.AbstractEventAtomicOperation.execute(AbstractEventAtomicOperation.java:56)
        at org.activiti.engine.impl.interceptor.CommandContext.performOperation(CommandContext.java:97)
        at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:636)
        at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:629)
        at org.activiti.engine.impl.pvm.runtime.AtomicOperationProcessStart.eventNotificationsCompleted(AtomicOperationProcessStart.java:64)
        at org.activiti.engine.impl.pvm.runtime.AbstractEventAtomicOperation.execute(AbstractEventAtomicOperation.java:56)
        at org.activiti.engine.impl.interceptor.CommandContext.performOperation(CommandContext.java:97)
        at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:636)
        at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:629)
        at org.activiti.engine.impl.persistence.entity.ExecutionEntity.start(ExecutionEntity.java:381)
        at org.activiti.engine.impl.cmd.StartProcessInstanceCmd.execute(StartProcessInstanceCmd.java:110)
        at org.activiti.engine.impl.cmd.StartProcessInstanceCmd.execute(StartProcessInstanceCmd.java:37)
        at org.activiti.engine.impl.interceptor.CommandInvoker.execute(CommandInvoker.java:24)
        at org.activiti.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:57)
        at org.activiti.spring.SpringTransactionInterceptor$1.doInTransaction(SpringTransactionInterceptor.java:47)
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
        at org.activiti.spring.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:45)
        at com.haulmont.bpm.core.engine.spring.ExtSpringTransactionInterceptor.execute(ExtSpringTransactionInterceptor.java:36)
        at org.activiti.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:31)
        at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:40)
        at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:35)
        at org.activiti.engine.impl.RuntimeServiceImpl.startProcessInstanceById(RuntimeServiceImpl.java:112)
        at com.haulmont.bpm.core.ProcessRuntimeManagerBean.startProcess(ProcessRuntimeManagerBean.java:85)
        at com.haulmont.bpm.service.ProcessRuntimeServiceBean.startProcess(ProcessRuntimeServiceBean.java:26)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
        at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:84)
        at com.haulmont.cuba.core.sys.ServiceInterceptor.aroundInvoke(ServiceInterceptor.java:96)
        at sun.reflect.GeneratedMethodAccessor156.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:627)
        at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:616)
        at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168)
        at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
        at com.sun.proxy.$Proxy301.startProcess(Unknown Source)
        at eu.octorilla.service.InvoiceServiceBean.startInvoiceBpm(InvoiceServiceBean.java:74)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
        at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:84)
        at com.haulmont.cuba.core.sys.ServiceInterceptor.aroundInvoke(ServiceInterceptor.java:96)
        at sun.reflect.GeneratedMethodAccessor156.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:627)
        at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:616)
        at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168)
        at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
        at com.sun.proxy.$Proxy305.startInvoiceBpm(Unknown Source)
        at eu.octorilla.listener.InvoiceEntityListener.onBeforeInsert(InvoiceEntityListener.java:18)
        at eu.octorilla.listener.InvoiceEntityListener.onBeforeInsert(InvoiceEntityListener.java:11)
        at com.haulmont.cuba.core.sys.listener.EntityListenerManager.fireListener(EntityListenerManager.java:242)
        at com.haulmont.cuba.core.sys.persistence.PersistenceImplSupport$OnCommitEntityVisitor.visit(PersistenceImplSupport.java:542)
        at com.haulmont.cuba.core.sys.persistence.PersistenceImplSupport.beforeStore(PersistenceImplSupport.java:236)
        at com.haulmont.cuba.core.sys.persistence.PersistenceImplSupport.traverseEntities(PersistenceImplSupport.java:222)
        at com.haulmont.cuba.core.sys.persistence.PersistenceImplSupport$ContainerResourceSynchronization.beforeCommit(PersistenceImplSupport.java:408)
        at org.springframework.transaction.support.TransactionSynchronizationUtils.triggerBeforeCommit(TransactionSynchronizationUtils.java:95)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCommit(AbstractPlatformTransactionManager.java:936)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:748)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:734)
        at com.haulmont.cuba.core.sys.TransactionImpl.commit(TransactionImpl.java:104)
        at com.haulmont.cuba.core.app.RdbmsStore.commit(RdbmsStore.java:476)
        at com.haulmont.cuba.core.app.DataManagerBean.commit(DataManagerBean.java:161)
        at com.haulmont.cuba.core.app.DataServiceBean.commit(DataServiceBean.java:41)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
        at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:84)
        at com.haulmont.cuba.core.sys.ServiceInterceptor.aroundInvoke(ServiceInterceptor.java:117)
        at sun.reflect.GeneratedMethodAccessor156.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:627)
        at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:616)
        at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168)
        at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
        at com.sun.proxy.$Proxy255.commit(Unknown Source)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at com.haulmont.cuba.core.sys.remoting.LocalServiceInvokerImpl.invoke(LocalServiceInvokerImpl.java:94)
        at com.haulmont.cuba.web.sys.remoting.LocalServiceProxy$LocalServiceInvocationHandler.invoke(LocalServiceProxy.java:154)
        at com.sun.proxy.$Proxy33.commit(Unknown Source)
        at com.haulmont.cuba.client.sys.DataManagerClientImpl.commit(DataManagerClientImpl.java:100)
        at com.haulmont.cuba.gui.data.impl.GenericDataSupplier.commit(GenericDataSupplier.java:105)
        at com.haulmont.cuba.gui.data.impl.DsContextImpl.commit(DsContextImpl.java:166)
        at com.haulmont.cuba.gui.components.EditorWindowDelegate.commit(EditorWindowDelegate.java:271)
        at com.haulmont.cuba.web.gui.WebWindow$Editor.commitAndClose(WebWindow.java:1773)
        at com.haulmont.cuba.gui.components.AbstractEditor.commitAndClose(AbstractEditor.java:111)
        at com.haulmont.cuba.gui.components.EditorWindowDelegate.lambda$wrapBy$1(EditorWindowDelegate.java:94)
        at com.haulmont.cuba.gui.components.actions.BaseAction.actionPerform(BaseAction.java:228)
        at com.haulmont.cuba.web.gui.components.WebButton.performAction(WebButton.java:46)
        at com.haulmont.cuba.web.gui.components.WebButton.lambda$new$61446b05$1(WebButton.java:38)
        at sun.reflect.GeneratedMethodAccessor261.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:510)
        at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:200)
        at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:163)
        at com.vaadin.server.AbstractClientConnector.fireEvent(AbstractClientConnector.java:1037)
        at com.vaadin.ui.Button.fireClick(Button.java:377)

Perhaps the bpm sample could be extended to demo a user task with candidate user en candidate groups.

What at first seemed to be an issue with me misunderstanding the concept of roles, groups and users turns out to be just a simple NullPointerException when assigning candidate users and groups.

In ProcessRuntimeManagerBean@430

    protected Set<User> getCandidateUsers(TaskEntity task) {
        Set<User> candidateUsers = new HashSet<>();
        EntityManager em = persistence.getEntityManager();
        Set<IdentityLink> candidates = task.getCandidates();
        for (IdentityLink candidate : candidates) {
            User user = em.find(User.class, UUID.fromString(candidate.getUserId()));
            if (user != null) {
                candidateUsers.add(user);
            } else {
                log.warn("ProcTask candidate user with id " + candidate.getUserId() + " not found");
            }
        }
        return candidateUsers;
    }

The code loops over all candidates, these can be users and groups. I noticed that at this moment the the users with a role R have already been added to the list for candidategroup R.

So a process role R maps to a task candidategroup R correctly.

But when iterating over all the candidates (oif the type IdentityLink) it tries to fetch them though the userService given the UUID.

For a candidage group the user UID field is always null, and the UUID.fromString throws an NPE.

A simple null check can fix the issue (or treat gourps and users seperately here)

I created an issue