Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to return two multi-instance tasks #3944

Open
Dengyren opened this issue Aug 10, 2024 · 15 comments
Open

How to return two multi-instance tasks #3944

Dengyren opened this issue Aug 10, 2024 · 15 comments

Comments

@Dengyren
Copy link

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

@tijsrademakers
Copy link
Contributor

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

@sscfaith
Copy link

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

@tijsrademakers
Copy link
Contributor

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

@sscfaith
Copy link

sscfaith commented Aug 12, 2024

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

@tijsrademakers
Copy link
Contributor

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.

@Dengyren
Copy link
Author

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
Copy link
Author

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();
    }
}

@tijsrademakers
Copy link
Contributor

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?

@sscfaith
Copy link

sscfaith commented Aug 12, 2024

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());

@Dengyren
Copy link
Author

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();
    }

}

@sscfaith
Copy link

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

@Dengyren
Copy link
Author

Dengyren commented Sep 6, 2024

Hello, is there any solution? @tijsrademakers

@ComeFromChina
Copy link

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

@Dengyren
Copy link
Author

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

@ComeFromChina
Copy link

7.0.0.M1 is ok! @tijsrademakers @Dengyren

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants