Activiti6 dynamic Task creation cannot complete

Created on 19 Dec 2018  路  4Comments  路  Source: Activiti/Activiti

Activiti6 is what I use to temporarily add a UserTask to the process. I want to do the following scenario:

When user A approves, user B is required to approve temporarily, and user B is not in the pre-defined process, so A UserTask needs to be added temporarily dynamically.

But I found two problems:

  1. The original Task can be completed, but the Task temporarily added cannot be completed. The following exception will be thrown:
org.activiti.engine.ActivitiException: Programmatic error: no current flow element found or invalid type: null. Halting.

    at org.activiti.engine.impl.agenda.TriggerExecutionOperation.run(TriggerExecutionOperation.java:49)
    at org.activiti.engine.impl.interceptor.CommandInvoker.executeOperation(CommandInvoker.java:73)
    at org.activiti.engine.impl.interceptor.CommandInvoker.executeOperations(CommandInvoker.java:57)
    at org.activiti.engine.impl.interceptor.CommandInvoker.execute(CommandInvoker.java:42)
    at org.activiti.engine.impl.interceptor.TransactionContextInterceptor.execute(TransactionContextInterceptor.java:48)
    at org.activiti.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:63)
    at org.activiti.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:29)
    at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:44)
    at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:39)
    at org.activiti.engine.impl.TaskServiceImpl.complete(TaskServiceImpl.java:182)
    at org.destiny.activiti.coreapi.TaskServiceTest.test(TaskServiceTest.java:357)
    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.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.activiti.engine.test.ActivitiRule$1.evaluate(ActivitiRule.java:116)
    at org.junit.rules.RunRules.evaluate(RunRules.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
  1. In the ACT_HI_TASKINST table, the task added temporarily does not have processInstanceId or other process information
    image

And there is my code:

main test

@Test
public void test() {
    ProcessInstance processInstance = activitiRule.getRuntimeService().startProcessInstanceByKey("my-process");
    TaskService taskService = activitiRule.getTaskService();
    Task task = taskService.createTaskQuery().singleResult();
    log.info("task: {}", ToStringBuilder.reflectionToString(task, ToStringStyle.JSON_STYLE));
    activitiRule.getManagementService().executeCommand(new ShareniuCountersignAddCmd(task.getExecutionId(), "camery"));
    Task destiny = taskService.createTaskQuery().taskAssignee("destiny").singleResult();
    taskService.complete(destiny.getId());
    historicTaskInstances = activitiRule.getHistoryService().createHistoricTaskInstanceQuery().list();
    Task camery = taskService.createTaskQuery().taskAssignee("camery").singleResult();
    taskService.complete(camery.getId());       // <=== will throw an Exception
}

CountersignAddCmd

public class CountersignAddCmd implements Command<Void> {

    protected String executionId;
    protected String assignee;

    public CountersignAddCmd(String executionId, String assignee) {
        this.executionId = executionId;
        this.assignee = assignee;
    }

    @Override
    public Void execute(CommandContext commandContext) {
        ProcessEngineConfigurationImpl processEngineConfiguration = commandContext.getProcessEngineConfiguration();
        RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
        TaskService taskService = processEngineConfiguration.getTaskService();

        IdGenerator idGenerator = processEngineConfiguration.getIdGenerator();
        // get Execution
        Execution execution = runtimeService.createExecutionQuery().executionId(executionId).singleResult();
        ExecutionEntity executionEntity = (ExecutionEntity) execution;
        // get parent ExecutionEntity 
        ExecutionEntity parent = executionEntity.getParent();
        // create ExecutionEntity 
        ExecutionEntity newExecution = commandContext.getExecutionEntityManager().createChildExecution(parent);
        newExecution.setActive(true);
        newExecution.setConcurrent(true);
        newExecution.setScope(false);
        Task newTask = taskService.createTaskQuery().executionId(executionId).singleResult();
        TaskEntity t = (TaskEntity) newTask;
        TaskEntity taskEntity = new TaskEntityImpl();
        taskEntity.setCreateTime(new Date());
        taskEntity.setProcessDefinitionId(t.getProcessDefinitionId());
        taskEntity.setTaskDefinitionKey(t.getTaskDefinitionKey());
        taskEntity.setProcessInstanceId(t.getProcessInstanceId());
        taskEntity.setExecutionId(newExecution.getId());
        taskEntity.setName(newTask.getName());
        String taskId = idGenerator.getNextId();
        taskEntity.setId(taskId);
        taskEntity.setRevision(0);
        taskEntity.setExecution(newExecution);
        taskEntity.setAssignee(assignee);
        taskService.saveTask(taskEntity);

        return null;
    }
}
question

Most helpful comment

@DestinyWang it will be great if you provide a project to reproduce the problem. A maven project hosted in GitHub with a test failing will be great. so we can debug what is going on and try to help.
With the information provided here it is quite difficult to see what might be failing.

@balsarori can you spot the problem?

All 4 comments

@DestinyWang it will be great if you provide a project to reproduce the problem. A maven project hosted in GitHub with a test failing will be great. so we can debug what is going on and try to help.
With the information provided here it is quite difficult to see what might be failing.

@balsarori can you spot the problem?

@salaboy ok here is the project:

activiti-demo

Hopefully you can figure out the cause of the problem, and if you can implement how can I do what I'm talking about

@DestinyWang adding a task on the fly to a process like that will not work. The engine doesn't know what to execute next when that task completes.

@balsarori What puzzles me is how do I tell the engine what to do next

Was this page helpful?
0 / 5 - 0 ratings