flowable-engine icon indicating copy to clipboard operation
flowable-engine copied to clipboard

How to return two multi-instance tasks

Open Dengyren opened this issue 1 year ago • 25 comments

image

this.runtimeService.createChangeActivityStateBuilder()
                .processInstanceId(currentTaskProcessInstanceId)
                .moveActivityIdsToSingleActivityId(returnTaskKeyList,  taskDefinitionKey)
                .changeState();

I hope that C can return B, but after executing the return, I found that there are no active tasks in ACT_RU_TASK. It is normal for C to return A. How to solve it? Environment: Java17, flowable 7.0.1

Dengyren avatar Aug 10 '24 06:08 Dengyren

If all executions of C should be moved to the single activity id B then did you try with the moveExecutionsToSingleActivityId method?

tijsrademakers avatar Aug 12 '24 06:08 tijsrademakers

Same question. 6.7.x and 6.8.0 is ok. But 6.8.1 - 7.0.1 is bad.

sscfaith avatar Aug 12 '24 08:08 sscfaith

I'm not following your comment @sscfaith. Can you give more details on what you are experiencing?

tijsrademakers avatar Aug 12 '24 09:08 tijsrademakers

image

this.runtimeService.createChangeActivityStateBuilder()
                .processInstanceId(currentTaskProcessInstanceId)
                .moveActivityIdsToSingleActivityId(returnTaskKeyList,  taskDefinitionKey)
                .changeState();

I hope that C can return B, but after executing the return, I found that there are no active tasks in ACT_RU_TASK. It is normal for C to return A. How to solve it? Environment: Java17, flowable 7.0.1

Same question as this, and this issue had same question

sscfaith avatar Aug 12 '24 12:08 sscfaith

Adding one liner messages doesn't help us to understand what you mean. I've commented on this issue today that it's good to try it with the moveExecutionsToSingleActivityId method, did you try that? If so, and it doesn't work, please attach a unit test so that we can reproduce the issue.

tijsrademakers avatar Aug 12 '24 12:08 tijsrademakers

If all executions of C should be moved to the single activity id B then did you try with the moveExecutionsToSingleActivityId method?

Tried, still failed

Dengyren avatar Aug 12 '24 12:08 Dengyren

Adding one liner messages doesn't help us to understand what you mean. I've commented on this issue today that it's good to try it with the moveExecutionsToSingleActivityId method, did you try that? If so, and it doesn't work, please attach a unit test so that we can reproduce the issue.

Test.zip


@SpringBootTest
class Demo3ApplicationTests {
    @Resource
    RepositoryService repositoryService;
    @Resource
    RuntimeService runtimeService;
    @Resource
    TaskService taskService;

    @Test
    void returnTaskTest() {
        Deployment deploy = repositoryService.createDeployment()
                .addClasspathResource("test.bpmn")
                .key("test")
                .name("test")
                .deploy();
        System.out.println("deploy id = " + deploy.getId());
        System.out.println("deploy name = " + deploy.getName());
        ProcessDefinition definition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deploy.getId()).singleResult();
        ProcessInstance processInstance = runtimeService
                .startProcessInstanceById(definition.getId());
        System.out.println("instance id = "+processInstance.getId());
        Task taskA = taskService.createTaskQuery()
                .processInstanceId(processInstance.getProcessInstanceId())
                .singleResult();
        taskService.complete(taskA.getId());
        Task taskB = taskService.createTaskQuery()
                .processInstanceId(processInstance.getProcessInstanceId())
                .singleResult();
        taskService.complete(taskB.getId());
        this.runtimeService.createChangeActivityStateBuilder()
                .processInstanceId(processInstance.getProcessInstanceId())
                .moveActivityIdTo("Activity_C", "Activity_B")
                .changeState();
    }
}

Dengyren avatar Aug 12 '24 14:08 Dengyren

Thanks for providing the unit test, but I don't see the method moveExecutionsToSingleActivityId being used. Can you change the unit test to use this?

tijsrademakers avatar Aug 12 '24 14:08 tijsrademakers

Thanks for providing the unit test, but I don't see the method moveExecutionsToSingleActivityId being used. Can you change the unit test to use this?

Test.zip

String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><definitions xmlns=\"http://www.omg.org/spec/BPMN/20100524/MODEL\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:bpmndi=\"http://www.omg.org/spec/BPMN/20100524/DI\" xmlns:flowable=\"http://flowable.org/bpmn\" xmlns:di=\"http://www.omg.org/spec/DD/20100524/DI\" xmlns:dc=\"http://www.omg.org/spec/DD/20100524/DC\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" targetNamespace=\"http://www.activiti.org/processdef\"><process id=\"abckey123456\" name=\"test\" isExecutable=\"true\"><startEvent id=\"Event_1f4jdvx\"><extensionElements><flowable:formData /></extensionElements><outgoing>Flow_0jbdt92</outgoing></startEvent><userTask id=\"Activity_B\" name=\"B\" flowable:candidateStrategy=\"10\" flowable:candidateParam=\"1,101\"><extensionElements><flowable:formData /></extensionElements><incoming>Flow_1iababq</incoming><outgoing>Flow_10mobwr</outgoing><multiInstanceLoopCharacteristics flowable:collection=\"${coll_userList}\"><loopCardinality xsi:type=\"tFormalExpression\">1</loopCardinality><completionCondition xsi:type=\"tFormalExpression\">${ nrOfCompletedInstances == 1 }</completionCondition></multiInstanceLoopCharacteristics></userTask><sequenceFlow id=\"Flow_0jbdt92\" sourceRef=\"Event_1f4jdvx\" targetRef=\"Activity_A\" /><intermediateThrowEvent id=\"Event_0wj33jc\"><incoming>Flow_1n9pjz5</incoming></intermediateThrowEvent><userTask id=\"Activity_A\" name=\"A\" flowable:candidateStrategy=\"30\" flowable:candidateParam=\"1\"><extensionElements><flowable:formData /></extensionElements><incoming>Flow_0jbdt92</incoming><outgoing>Flow_1iababq</outgoing></userTask><sequenceFlow id=\"Flow_1iababq\" sourceRef=\"Activity_A\" targetRef=\"Activity_B\" /><userTask id=\"Activity_C\" name=\"C\" flowable:candidateStrategy=\"30\" flowable:candidateParam=\"117,104\"><extensionElements><flowable:formData /></extensionElements><incoming>Flow_10mobwr</incoming><outgoing>Flow_1n9pjz5</outgoing><multiInstanceLoopCharacteristics flowable:collection=\"${coll_userList}\"><loopCardinality xsi:type=\"tFormalExpression\">1</loopCardinality><completionCondition xsi:type=\"tFormalExpression\">${ nrOfCompletedInstances == 1 }</completionCondition></multiInstanceLoopCharacteristics></userTask><sequenceFlow id=\"Flow_10mobwr\" sourceRef=\"Activity_B\" targetRef=\"Activity_C\" /><sequenceFlow id=\"Flow_1n9pjz5\" sourceRef=\"Activity_C\" targetRef=\"Event_0wj33jc\" /></process><bpmndi:BPMNDiagram id=\"BPMNDiagram\"><bpmndi:BPMNPlane id=\"bpm_order_di\" bpmnElement=\"abckey123456\"><bpmndi:BPMNShape id=\"Event_1f4jdvx_di\" bpmnElement=\"Event_1f4jdvx\"><dc:Bounds x=\"22\" y=\"302\" width=\"36\" height=\"36\" /></bpmndi:BPMNShape><bpmndi:BPMNShape id=\"Activity_B_di\" bpmnElement=\"Activity_B\"><dc:Bounds x=\"280\" y=\"280\" width=\"100\" height=\"80\" /></bpmndi:BPMNShape><bpmndi:BPMNShape id=\"Event_0wj33jc_di\" bpmnElement=\"Event_0wj33jc\"><dc:Bounds x=\"602\" y=\"302\" width=\"36\" height=\"36\" /></bpmndi:BPMNShape><bpmndi:BPMNShape id=\"Activity_A_di\" bpmnElement=\"Activity_A\"><dc:Bounds x=\"120\" y=\"280\" width=\"100\" height=\"80\" /><bpmndi:BPMNLabel /></bpmndi:BPMNShape><bpmndi:BPMNShape id=\"Activity_C_di\" bpmnElement=\"Activity_C\"><dc:Bounds x=\"430\" y=\"280\" width=\"100\" height=\"80\" /></bpmndi:BPMNShape><bpmndi:BPMNEdge id=\"Flow_0jbdt92_di\" bpmnElement=\"Flow_0jbdt92\"><di:waypoint x=\"58\" y=\"320\" /><di:waypoint x=\"120\" y=\"320\" /></bpmndi:BPMNEdge><bpmndi:BPMNEdge id=\"Flow_1iababq_di\" bpmnElement=\"Flow_1iababq\"><di:waypoint x=\"220\" y=\"320\" /><di:waypoint x=\"280\" y=\"320\" /></bpmndi:BPMNEdge><bpmndi:BPMNEdge id=\"Flow_10mobwr_di\" bpmnElement=\"Flow_10mobwr\"><di:waypoint x=\"380\" y=\"320\" /><di:waypoint x=\"430\" y=\"320\" /></bpmndi:BPMNEdge><bpmndi:BPMNEdge id=\"Flow_1n9pjz5_di\" bpmnElement=\"Flow_1n9pjz5\"><di:waypoint x=\"530\" y=\"320\" /><di:waypoint x=\"602\" y=\"320\" /></bpmndi:BPMNEdge></bpmndi:BPMNPlane></bpmndi:BPMNDiagram></definitions>\n";

        BpmnXMLConverter converter = new BpmnXMLConverter();
        BpmnModel bpmnModel = converter.convertToBpmnModel(new StringStreamSource(xml), false, false);
        Deployment deploy = repositoryService.createDeployment()
                .addBpmnModel("test.bpmn20.xml", bpmnModel)
                .key("test")
                .name("test")
                .deploy();
        System.err.println("deploy id = " + deploy.getId());
        System.err.println("deploy name = " + deploy.getName());
        ProcessDefinition definition = repositoryService
                .createProcessDefinitionQuery()
                .deploymentId(deploy.getId())
                .singleResult();
        ProcessInstance processInstance = runtimeService
                .startProcessInstanceById(definition.getId());
        System.err.println("instance id = " + processInstance.getId());

        // Activity_A
        Task taskA = taskService.createTaskQuery()
                .processInstanceId(processInstance.getProcessInstanceId())
                .singleResult();
        taskService.complete(taskA.getId());

        // Activity_B
        Task taskB = taskService.createTaskQuery()
                .processInstanceId(processInstance.getProcessInstanceId())
                .singleResult();
        taskService.complete(taskB.getId());

        // Method-1、Activity_C to Activity_B use moveActivityIdTo
//        runtimeService.createChangeActivityStateBuilder()
//                .processInstanceId(processInstance.getProcessInstanceId())
//                .moveActivityIdTo("Activity_C", "Activity_B")
//                .changeState();

        // Method-2、Activity_C to Activity_B use moveExecutionsToSingleActivityId
        List<Execution> executions = runtimeService.createExecutionQuery().parentId(processInstance.getProcessInstanceId()).list();
        List<String> executionIds = new ArrayList<>();
        executions.forEach(execution -> executionIds.add(execution.getId()));
        runtimeService.createChangeActivityStateBuilder()
                .moveExecutionsToSingleActivityId(executionIds, "Activity_B")
                .changeState();
        // Both methods cause tasks disappear when use version 6.8.1 ~ 7.0.1, but 6.7.x and 6.8.0 is ok.

        List<Task> list = taskService.createTaskQuery()
                .processInstanceId(processInstance.getId())
                .list();

        // Version 6.8.1 ~ 7.0.1 size is 0, 6.7.x and 6.8.0 size is 1.
        System.err.println("task list size = " + list.size());

sscfaith avatar Aug 12 '24 14:08 sscfaith

Thanks for providing the unit test, but I don't see the method moveExecutionsToSingleActivityId being used. Can you change the unit test to use this?


@SpringBootTest
class Demo3ApplicationTests {


    @Resource
    RepositoryService repositoryService;


    @Resource
    RuntimeService runtimeService;

    @Resource
    TaskService taskService;

    @Test
    void init() {
        Deployment deploy = repositoryService.createDeployment()
                .addClasspathResource("test.bpmn")
                .key("test")
                .name("test")
                .deploy();
        System.out.println("deploy id = " + deploy.getId());
        System.out.println("deploy name = " + deploy.getName());
        ProcessDefinition definition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deploy.getId()).singleResult();
        ProcessInstance processInstance = runtimeService
                .startProcessInstanceById(definition.getId());
        System.out.println("instance id = "+processInstance.getId());
        Task taskA = taskService.createTaskQuery()
                .processInstanceId(processInstance.getProcessInstanceId())
                .singleResult();
        taskService.complete(taskA.getId());
        Task taskB = taskService.createTaskQuery()
                .processInstanceId(processInstance.getProcessInstanceId())
                .singleResult();
        taskService.complete(taskB.getId());
        List<Execution> executions = runtimeService.createExecutionQuery().parentId(processInstance.getProcessInstanceId()).list();
        this.runtimeService.createChangeActivityStateBuilder()
                .processInstanceId(processInstance.getProcessInstanceId())
                .moveExecutionsToSingleActivityId(executions.stream().map(Execution::getId).toList(), "Activity_B")
                .changeState();
    }

}

Dengyren avatar Aug 12 '24 15:08 Dengyren

Hi, is this a bug or should we use other APIs? @tijsrademakers

sscfaith avatar Aug 15 '24 07:08 sscfaith

Hello, is there any solution? @tijsrademakers

Dengyren avatar Sep 06 '24 06:09 Dengyren

Is there a solution? How to solve it? @tijsrademakers @Dengyren

ComeFromChina avatar Sep 20 '24 05:09 ComeFromChina

Is there a solution? How to solve it? @tijsrademakers @Dengyren

use 6.7.x to 6.8.0, or business restrictions can only return single signing tasks

Dengyren avatar Sep 20 '24 05:09 Dengyren

7.0.0.M1 is ok! @tijsrademakers @Dengyren

ComeFromChina avatar Sep 23 '24 05:09 ComeFromChina

7.1.0 still not working. How to solve this problem, I'm in a hurry. PLS

sscfaith avatar Nov 25 '24 08:11 sscfaith

Same question as this

maobole avatar Nov 27 '24 16:11 maobole

I've tested the unit test provided and this just runs green. So please provide a failing unit test showing the issue that you are mentioning.

tijsrademakers avatar Nov 28 '24 08:11 tijsrademakers

Thanks for providing the unit test, but I don't see the method moveExecutionsToSingleActivityId being used. Can you change the unit test to use this?

Test.zip

String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><definitions xmlns=\"http://www.omg.org/spec/BPMN/20100524/MODEL\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:bpmndi=\"http://www.omg.org/spec/BPMN/20100524/DI\" xmlns:flowable=\"http://flowable.org/bpmn\" xmlns:di=\"http://www.omg.org/spec/DD/20100524/DI\" xmlns:dc=\"http://www.omg.org/spec/DD/20100524/DC\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" targetNamespace=\"http://www.activiti.org/processdef\"><process id=\"abckey123456\" name=\"test\" isExecutable=\"true\"><startEvent id=\"Event_1f4jdvx\"><extensionElements><flowable:formData /></extensionElements><outgoing>Flow_0jbdt92</outgoing></startEvent><userTask id=\"Activity_B\" name=\"B\" flowable:candidateStrategy=\"10\" flowable:candidateParam=\"1,101\"><extensionElements><flowable:formData /></extensionElements><incoming>Flow_1iababq</incoming><outgoing>Flow_10mobwr</outgoing><multiInstanceLoopCharacteristics flowable:collection=\"${coll_userList}\"><loopCardinality xsi:type=\"tFormalExpression\">1</loopCardinality><completionCondition xsi:type=\"tFormalExpression\">${ nrOfCompletedInstances == 1 }</completionCondition></multiInstanceLoopCharacteristics></userTask><sequenceFlow id=\"Flow_0jbdt92\" sourceRef=\"Event_1f4jdvx\" targetRef=\"Activity_A\" /><intermediateThrowEvent id=\"Event_0wj33jc\"><incoming>Flow_1n9pjz5</incoming></intermediateThrowEvent><userTask id=\"Activity_A\" name=\"A\" flowable:candidateStrategy=\"30\" flowable:candidateParam=\"1\"><extensionElements><flowable:formData /></extensionElements><incoming>Flow_0jbdt92</incoming><outgoing>Flow_1iababq</outgoing></userTask><sequenceFlow id=\"Flow_1iababq\" sourceRef=\"Activity_A\" targetRef=\"Activity_B\" /><userTask id=\"Activity_C\" name=\"C\" flowable:candidateStrategy=\"30\" flowable:candidateParam=\"117,104\"><extensionElements><flowable:formData /></extensionElements><incoming>Flow_10mobwr</incoming><outgoing>Flow_1n9pjz5</outgoing><multiInstanceLoopCharacteristics flowable:collection=\"${coll_userList}\"><loopCardinality xsi:type=\"tFormalExpression\">1</loopCardinality><completionCondition xsi:type=\"tFormalExpression\">${ nrOfCompletedInstances == 1 }</completionCondition></multiInstanceLoopCharacteristics></userTask><sequenceFlow id=\"Flow_10mobwr\" sourceRef=\"Activity_B\" targetRef=\"Activity_C\" /><sequenceFlow id=\"Flow_1n9pjz5\" sourceRef=\"Activity_C\" targetRef=\"Event_0wj33jc\" /></process><bpmndi:BPMNDiagram id=\"BPMNDiagram\"><bpmndi:BPMNPlane id=\"bpm_order_di\" bpmnElement=\"abckey123456\"><bpmndi:BPMNShape id=\"Event_1f4jdvx_di\" bpmnElement=\"Event_1f4jdvx\"><dc:Bounds x=\"22\" y=\"302\" width=\"36\" height=\"36\" /></bpmndi:BPMNShape><bpmndi:BPMNShape id=\"Activity_B_di\" bpmnElement=\"Activity_B\"><dc:Bounds x=\"280\" y=\"280\" width=\"100\" height=\"80\" /></bpmndi:BPMNShape><bpmndi:BPMNShape id=\"Event_0wj33jc_di\" bpmnElement=\"Event_0wj33jc\"><dc:Bounds x=\"602\" y=\"302\" width=\"36\" height=\"36\" /></bpmndi:BPMNShape><bpmndi:BPMNShape id=\"Activity_A_di\" bpmnElement=\"Activity_A\"><dc:Bounds x=\"120\" y=\"280\" width=\"100\" height=\"80\" /><bpmndi:BPMNLabel /></bpmndi:BPMNShape><bpmndi:BPMNShape id=\"Activity_C_di\" bpmnElement=\"Activity_C\"><dc:Bounds x=\"430\" y=\"280\" width=\"100\" height=\"80\" /></bpmndi:BPMNShape><bpmndi:BPMNEdge id=\"Flow_0jbdt92_di\" bpmnElement=\"Flow_0jbdt92\"><di:waypoint x=\"58\" y=\"320\" /><di:waypoint x=\"120\" y=\"320\" /></bpmndi:BPMNEdge><bpmndi:BPMNEdge id=\"Flow_1iababq_di\" bpmnElement=\"Flow_1iababq\"><di:waypoint x=\"220\" y=\"320\" /><di:waypoint x=\"280\" y=\"320\" /></bpmndi:BPMNEdge><bpmndi:BPMNEdge id=\"Flow_10mobwr_di\" bpmnElement=\"Flow_10mobwr\"><di:waypoint x=\"380\" y=\"320\" /><di:waypoint x=\"430\" y=\"320\" /></bpmndi:BPMNEdge><bpmndi:BPMNEdge id=\"Flow_1n9pjz5_di\" bpmnElement=\"Flow_1n9pjz5\"><di:waypoint x=\"530\" y=\"320\" /><di:waypoint x=\"602\" y=\"320\" /></bpmndi:BPMNEdge></bpmndi:BPMNPlane></bpmndi:BPMNDiagram></definitions>\n";

        BpmnXMLConverter converter = new BpmnXMLConverter();
        BpmnModel bpmnModel = converter.convertToBpmnModel(new StringStreamSource(xml), false, false);
        Deployment deploy = repositoryService.createDeployment()
                .addBpmnModel("test.bpmn20.xml", bpmnModel)
                .key("test")
                .name("test")
                .deploy();
        System.err.println("deploy id = " + deploy.getId());
        System.err.println("deploy name = " + deploy.getName());
        ProcessDefinition definition = repositoryService
                .createProcessDefinitionQuery()
                .deploymentId(deploy.getId())
                .singleResult();
        ProcessInstance processInstance = runtimeService
                .startProcessInstanceById(definition.getId());
        System.err.println("instance id = " + processInstance.getId());

        // Activity_A
        Task taskA = taskService.createTaskQuery()
                .processInstanceId(processInstance.getProcessInstanceId())
                .singleResult();
        taskService.complete(taskA.getId());

        // Activity_B
        Task taskB = taskService.createTaskQuery()
                .processInstanceId(processInstance.getProcessInstanceId())
                .singleResult();
        taskService.complete(taskB.getId());

        // Method-1、Activity_C to Activity_B use moveActivityIdTo
//        runtimeService.createChangeActivityStateBuilder()
//                .processInstanceId(processInstance.getProcessInstanceId())
//                .moveActivityIdTo("Activity_C", "Activity_B")
//                .changeState();

        // Method-2、Activity_C to Activity_B use moveExecutionsToSingleActivityId
        List<Execution> executions = runtimeService.createExecutionQuery().parentId(processInstance.getProcessInstanceId()).list();
        List<String> executionIds = new ArrayList<>();
        executions.forEach(execution -> executionIds.add(execution.getId()));
        runtimeService.createChangeActivityStateBuilder()
                .moveExecutionsToSingleActivityId(executionIds, "Activity_B")
                .changeState();
        // Both methods cause tasks disappear when use version 6.8.1 ~ 7.0.1, but 6.7.x and 6.8.0 is ok.

        List<Task> list = taskService.createTaskQuery()
                .processInstanceId(processInstance.getId())
                .list();

        // Version 6.8.1 ~ 7.0.1 size is 0, 6.7.x and 6.8.0 size is 1.
        System.err.println("task list size = " + list.size());

@tijsrademakers The unit test definitely runs green, but the results differ between versions. Check my code comments.

sscfaith avatar Nov 28 '24 08:11 sscfaith

I've tested the unit test provided and this just runs green. So please provide a failing unit test showing the issue that you are mentioning.

The unit test was successful, but the return task can no longer be found in the database.

Dengyren avatar Nov 28 '24 08:11 Dengyren

I've tested the unit test provided and this just runs green. So please provide a failing unit test showing the issue that you are mentioning.

The return task does not appear in the table ACT_RETURN_TASK.

Dengyren avatar Nov 28 '24 08:11 Dengyren

Thanks, it was clear now. Can you check with the latest version from the main branch? This should now have been fixed with this commit https://github.com/flowable/flowable-engine/commit/219ecb955b1347953c97a41355c551a348ce4dc9

tijsrademakers avatar Dec 02 '24 13:12 tijsrademakers

Thanks, it was clear now. Can you check with the latest version from the main branch? This should now have been fixed with this commit 219ecb9

I tested using the 7.1.1-SNAPSHOT version and the issue was resolved. Thank you.

Dengyren avatar Dec 09 '24 02:12 Dengyren

7.1.0 still not working. How to solve this problem, I'm in a hurry. PLS

Would you like to try it too?

Dengyren avatar Dec 09 '24 02:12 Dengyren

Thanks, it was clear now. Can you check with the latest version from the main branch? This should now have been fixed with this commit 219ecb9

When do you expect to release the official fixed version?

Dengyren avatar Dec 14 '24 07:12 Dengyren