Java - Camunda BPMN模型API:如何保存有效的xml?

问题描述 投票:2回答:1

我正在构建一些测试BPMN 2.0模型并将它们保存到Java项目中的xml文件中,遵循官方doc提供的示例,在本例中为示例2。

我在我的pom中导入了lib,如下所示:

<!-- https://mvnrepository.com/artifact/org.camunda.bpm.model/camunda-bpmn-model -->
<dependency>
    <groupId>org.camunda.bpm.model</groupId>
    <artifactId>camunda-bpmn-model</artifactId>
    <version>7.10.0</version>
</dependency>

这是我的测试类,遵循示例2:

import org.camunda.bpm.model.bpmn.Bpmn;
import org.camunda.bpm.model.bpmn.BpmnModelInstance;
import org.camunda.bpm.model.bpmn.instance.*;
import org.camunda.bpm.model.bpmn.instance.Process;

import java.io.File;
import java.io.IOException;

public class Test {
    protected static <T extends BpmnModelElementInstance> T createElement(BpmnModelInstance modelInstance, BpmnModelElementInstance parentElement, String id, Class<T> elementClass) {
        T element = modelInstance.newInstance(elementClass);
        element.setAttributeValue("id", id, true);
        parentElement.addChildElement(element);
        return element;
    }

    public static SequenceFlow createSequenceFlow(BpmnModelInstance modelInstance, Process process, FlowNode from, FlowNode to) {
        String identifier = from.getId() + "-" + to.getId();
        SequenceFlow sequenceFlow = createElement(modelInstance, process, identifier, SequenceFlow.class);
        process.addChildElement(sequenceFlow);
        sequenceFlow.setSource(from);
        from.getOutgoing().add(sequenceFlow);
        sequenceFlow.setTarget(to);
        to.getIncoming().add(sequenceFlow);
        return sequenceFlow;
    }

    public static void main(String[] args) throws IOException {
        // create an empty model
        BpmnModelInstance modelInstance = Bpmn.createEmptyModel();
        Definitions definitions = modelInstance.newInstance(Definitions.class);
        definitions.setTargetNamespace("http://camunda.org/examples");
        modelInstance.setDefinitions(definitions);

        // create a process
        Process process = modelInstance.newInstance(Process.class);
        process.setId("process");
        definitions.addChildElement(process);

        // create elements
        StartEvent startEvent = createElement(modelInstance, process, "start", StartEvent.class);
        ParallelGateway fork = createElement(modelInstance, process, "fork", ParallelGateway.class);
        ServiceTask task1 = createElement(modelInstance, process, "task1", ServiceTask.class);
        task1.setName("Service Task");
        UserTask task2 = createElement(modelInstance, process, "task2", UserTask.class);
        task2.setName("User Task");
        ParallelGateway join = createElement(modelInstance, process, "join", ParallelGateway.class);
        EndEvent endEvent = createElement(modelInstance, process, "end", EndEvent.class);

        // create flows
        createSequenceFlow(modelInstance, process, startEvent, fork);
        createSequenceFlow(modelInstance, process, fork, task1);
        createSequenceFlow(modelInstance, process, fork, task2);
        createSequenceFlow(modelInstance, process, task1, join);
        createSequenceFlow(modelInstance, process, task2, join);
        createSequenceFlow(modelInstance, process, join, endEvent);

        // validate and write model to file
        Bpmn.validateModel(modelInstance);
        File file = new File("bpmn-model.bpmn.xml");
        file.createNewFile();
        Bpmn.writeModelToFile(file, modelInstance);
    }
}

这里生成的BPMN 2.0 xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<definitions id="definitions_7b2df680-1d9c-4897-ba8b-a83548ab937f" targetNamespace="http://camunda.org/examples" xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL">
  <process id="process">
    <startEvent id="start">
      <outgoing>start-fork</outgoing>
    </startEvent>
    <parallelGateway id="fork">
      <incoming>start-fork</incoming>
      <outgoing>fork-task1</outgoing>
      <outgoing>fork-task2</outgoing>
    </parallelGateway>
    <serviceTask id="task1" name="Service Task">
      <incoming>fork-task1</incoming>
      <outgoing>task1-join</outgoing>
    </serviceTask>
    <userTask id="task2" name="User Task">
      <incoming>fork-task2</incoming>
      <outgoing>task2-join</outgoing>
    </userTask>
    <parallelGateway id="join">
      <incoming>task1-join</incoming>
      <incoming>task2-join</incoming>
      <outgoing>join-end</outgoing>
    </parallelGateway>
    <endEvent id="end">
      <incoming>join-end</incoming>
    </endEvent>
    <sequenceFlow id="start-fork" sourceRef="start" targetRef="fork"/>
    <sequenceFlow id="fork-task1" sourceRef="fork" targetRef="task1"/>
    <sequenceFlow id="fork-task2" sourceRef="fork" targetRef="task2"/>
    <sequenceFlow id="task1-join" sourceRef="task1" targetRef="join"/>
    <sequenceFlow id="task2-join" sourceRef="task2" targetRef="join"/>
    <sequenceFlow id="join-end" sourceRef="join" targetRef="end"/>
  </process>
</definitions>

虽然验证方法,但在尝试使用Camunda Modeler应用程序和qazxsw poi显示BPMN时,生成的xml似乎无效。

这个例子有什么问题,因此我的代码?如何使生成的xml有效?由于bpmn 2.0是一个标准,我也对这个问题感到有些惊讶。

java xml bpmn camunda camunda-modeler
1个回答
2
投票

我终于通过切换到流畅的模型构建器API,遵循此bpmn.io来实现它

这是我更新的测试类:

https://blog.camunda.com/post/2014/02/the-new-camunda-bpmn-model-api/

这是生成的xml:

import org.camunda.bpm.model.bpmn.Bpmn;
import org.camunda.bpm.model.bpmn.BpmnModelInstance;
import org.camunda.bpm.model.bpmn.GatewayDirection;

import java.io.File;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException {
        BpmnModelInstance modelInstance = Bpmn.createProcess()
            .name("BPMN API Invoice Process")
            .executable()
            .startEvent()
            .name("Invoice received")
            .camundaFormKey("embedded:app:forms/start-form.html")
            .userTask()
            .name("Assign Approver")
            .camundaFormKey("embedded:app:forms/assign-approver.html")
            .camundaAssignee("demo")
            .userTask()
            .id("approveInvoice")
            .name("Approve Invoice")
            .camundaFormKey("embedded:app:forms/approve-invoice.html")
            .camundaAssignee("${approver}")
            .exclusiveGateway()
            .name("Invoice approved?")
            .gatewayDirection(GatewayDirection.Diverging)
            .condition("yes", "${approved}")
            .userTask()
            .name("Prepare Bank Transfer")
            .camundaFormKey("embedded:app:forms/prepare-bank-transfer.html")
            .camundaCandidateGroups("accounting")
            .serviceTask()
            .name("Archive Invoice")
            .endEvent()
            .name("Invoice processed")
            .moveToLastGateway()
            .condition("no", "${!approved}")
            .userTask()
            .name("Review Invoice")
            .camundaFormKey("embedded:app:forms/review-invoice.html")
            .camundaAssignee("demo")
            .exclusiveGateway()
            .name("Review successful?")
            .gatewayDirection(GatewayDirection.Diverging)
            .condition("no", "${!clarified}")
            .endEvent()
            .name("Invoice not processed")
            .moveToLastGateway()
            .condition("yes", "${clarified}")
            .connectTo("approveInvoice")
            .done();

        // validate and write model to file
        Bpmn.validateModel(modelInstance);
        File file = new File("bpmn-model.bpmn.xml");
        file.createNewFile();

        String bpmnString = Bpmn.convertToString(modelInstance);
        System.out.println("bpmnString");
        System.out.println(bpmnString);

        Bpmn.writeModelToFile(file, modelInstance);
    }
}

通过将它与上面的xml进行比较,我注意到之前没有的一些新的<?xml version="1.0" encoding="UTF-8" standalone="no"?> <definitions xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="definitions_3bd3e094-3e53-4644-af0c-1a048653920c" targetNamespace="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"> <process id="process_e14ca74e-6095-4a2b-bced-debcb3b37954" isExecutable="true" name="BPMN API Invoice Process"> <startEvent camunda:formKey="embedded:app:forms/start-form.html" id="startEvent_e8daa33a-af99-4b7a-87ee-200b0e7bedcd" name="Invoice received"> <outgoing>sequenceFlow_cb28e7e5-ebc0-4f27-b8b2-24403ab87ce3</outgoing> </startEvent> <userTask camunda:assignee="demo" camunda:formKey="embedded:app:forms/assign-approver.html" id="userTask_029f48b9-de24-4292-af49-845e81fdcc4b" name="Assign Approver"> <incoming>sequenceFlow_cb28e7e5-ebc0-4f27-b8b2-24403ab87ce3</incoming> <outgoing>sequenceFlow_57a81fcd-fb35-42cd-afca-7c4c7914936d</outgoing> </userTask> <sequenceFlow id="sequenceFlow_cb28e7e5-ebc0-4f27-b8b2-24403ab87ce3" sourceRef="startEvent_e8daa33a-af99-4b7a-87ee-200b0e7bedcd" targetRef="userTask_029f48b9-de24-4292-af49-845e81fdcc4b"/> <userTask camunda:assignee="${approver}" camunda:formKey="embedded:app:forms/approve-invoice.html" id="approveInvoice" name="Approve Invoice"> <incoming>sequenceFlow_57a81fcd-fb35-42cd-afca-7c4c7914936d</incoming> <incoming>sequenceFlow_6987bcb8-5f6a-467b-9b25-e21b90dd0d4d</incoming> <outgoing>sequenceFlow_1fe15a36-427e-4000-8fc7-50b8925ea1e5</outgoing> </userTask> <sequenceFlow id="sequenceFlow_57a81fcd-fb35-42cd-afca-7c4c7914936d" sourceRef="userTask_029f48b9-de24-4292-af49-845e81fdcc4b" targetRef="approveInvoice"/> <exclusiveGateway gatewayDirection="Diverging" id="exclusiveGateway_b66a0444-2889-4cae-ac78-c1f65405ba0b" name="Invoice approved?"> <incoming>sequenceFlow_1fe15a36-427e-4000-8fc7-50b8925ea1e5</incoming> <outgoing>sequenceFlow_9156c1d4-f756-447b-a384-e3bf17c43ff4</outgoing> <outgoing>sequenceFlow_29bab2ba-6108-4731-94c3-93a6955d1946</outgoing> </exclusiveGateway> <sequenceFlow id="sequenceFlow_1fe15a36-427e-4000-8fc7-50b8925ea1e5" sourceRef="approveInvoice" targetRef="exclusiveGateway_b66a0444-2889-4cae-ac78-c1f65405ba0b"/> <sequenceFlow id="sequenceFlow_9156c1d4-f756-447b-a384-e3bf17c43ff4" name="yes" sourceRef="exclusiveGateway_b66a0444-2889-4cae-ac78-c1f65405ba0b" targetRef="userTask_79a63b4f-96a7-43d7-aab3-e8e0e83769e5"> <conditionExpression id="conditionExpression_13d7607b-d7e7-4fa4-a364-aeabff28a0f1">${approved}</conditionExpression> </sequenceFlow> <userTask camunda:candidateGroups="accounting" camunda:formKey="embedded:app:forms/prepare-bank-transfer.html" id="userTask_79a63b4f-96a7-43d7-aab3-e8e0e83769e5" name="Prepare Bank Transfer"> <incoming>sequenceFlow_9156c1d4-f756-447b-a384-e3bf17c43ff4</incoming> <outgoing>sequenceFlow_b82e04ab-a0cc-4969-989a-1ec64d74d990</outgoing> </userTask> <serviceTask id="serviceTask_9d976f99-f8fb-4705-ae6d-a606758111f4" name="Archive Invoice"> <incoming>sequenceFlow_b82e04ab-a0cc-4969-989a-1ec64d74d990</incoming> <outgoing>sequenceFlow_f0f99688-25b1-417e-9a5d-0d17503cb3ba</outgoing> </serviceTask> <sequenceFlow id="sequenceFlow_b82e04ab-a0cc-4969-989a-1ec64d74d990" sourceRef="userTask_79a63b4f-96a7-43d7-aab3-e8e0e83769e5" targetRef="serviceTask_9d976f99-f8fb-4705-ae6d-a606758111f4"/> <endEvent id="endEvent_affc9949-819a-4b79-98bd-0f2fd844d014" name="Invoice processed"> <incoming>sequenceFlow_f0f99688-25b1-417e-9a5d-0d17503cb3ba</incoming> </endEvent> <sequenceFlow id="sequenceFlow_f0f99688-25b1-417e-9a5d-0d17503cb3ba" sourceRef="serviceTask_9d976f99-f8fb-4705-ae6d-a606758111f4" targetRef="endEvent_affc9949-819a-4b79-98bd-0f2fd844d014"/> <sequenceFlow id="sequenceFlow_29bab2ba-6108-4731-94c3-93a6955d1946" name="no" sourceRef="exclusiveGateway_b66a0444-2889-4cae-ac78-c1f65405ba0b" targetRef="userTask_7b955191-5741-44df-b7ba-d154ddfbe616"> <conditionExpression id="conditionExpression_ce06d35f-8638-4699-802b-7f1b94732f46">${!approved}</conditionExpression> </sequenceFlow> <userTask camunda:assignee="demo" camunda:formKey="embedded:app:forms/review-invoice.html" id="userTask_7b955191-5741-44df-b7ba-d154ddfbe616" name="Review Invoice"> <incoming>sequenceFlow_29bab2ba-6108-4731-94c3-93a6955d1946</incoming> <outgoing>sequenceFlow_74d95e16-7907-4000-9ffb-cdba8c3ddde4</outgoing> </userTask> <exclusiveGateway gatewayDirection="Diverging" id="exclusiveGateway_5aa645c5-a5e7-4453-8498-8462092b85b1" name="Review successful?"> <incoming>sequenceFlow_74d95e16-7907-4000-9ffb-cdba8c3ddde4</incoming> <outgoing>sequenceFlow_3bf21b37-c534-4541-b84f-03d3fe05c989</outgoing> <outgoing>sequenceFlow_6987bcb8-5f6a-467b-9b25-e21b90dd0d4d</outgoing> </exclusiveGateway> <sequenceFlow id="sequenceFlow_74d95e16-7907-4000-9ffb-cdba8c3ddde4" sourceRef="userTask_7b955191-5741-44df-b7ba-d154ddfbe616" targetRef="exclusiveGateway_5aa645c5-a5e7-4453-8498-8462092b85b1"/> <sequenceFlow id="sequenceFlow_3bf21b37-c534-4541-b84f-03d3fe05c989" name="no" sourceRef="exclusiveGateway_5aa645c5-a5e7-4453-8498-8462092b85b1" targetRef="endEvent_68057c88-fa46-43cc-a93c-774b26be7b50"> <conditionExpression id="conditionExpression_8bb43e50-dd2f-40ba-9cc9-91a69813a835">${!clarified}</conditionExpression> </sequenceFlow> <endEvent id="endEvent_68057c88-fa46-43cc-a93c-774b26be7b50" name="Invoice not processed"> <incoming>sequenceFlow_3bf21b37-c534-4541-b84f-03d3fe05c989</incoming> </endEvent> <sequenceFlow id="sequenceFlow_6987bcb8-5f6a-467b-9b25-e21b90dd0d4d" name="yes" sourceRef="exclusiveGateway_5aa645c5-a5e7-4453-8498-8462092b85b1" targetRef="approveInvoice"> <conditionExpression id="conditionExpression_c3fb4bcf-905a-47dd-84cf-6cfe1980ca2e">${clarified}</conditionExpression> </sequenceFlow> </process> <bpmndi:BPMNDiagram id="BPMNDiagram_946186ab-976d-40e2-9ed2-4672566340a2"> <bpmndi:BPMNPlane bpmnElement="process_e14ca74e-6095-4a2b-bced-debcb3b37954" id="BPMNPlane_78d2c2b7-e5e7-414f-abae-0dcddaefbdfd"> <bpmndi:BPMNShape bpmnElement="startEvent_e8daa33a-af99-4b7a-87ee-200b0e7bedcd" id="BPMNShape_2da46013-859f-418a-8612-25bd57aabb52"> <dc:Bounds height="36.0" width="36.0" x="100.0" y="100.0"/> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="userTask_029f48b9-de24-4292-af49-845e81fdcc4b" id="BPMNShape_79fd4553-cfb0-4740-b4fe-093d1c96474b"> <dc:Bounds height="80.0" width="100.0" x="186.0" y="78.0"/> </bpmndi:BPMNShape> <bpmndi:BPMNEdge bpmnElement="sequenceFlow_cb28e7e5-ebc0-4f27-b8b2-24403ab87ce3" id="BPMNEdge_77315869-b425-4daf-85b6-6121867d91bc"> <di:waypoint x="136.0" y="118.0"/> <di:waypoint x="186.0" y="118.0"/> </bpmndi:BPMNEdge> <bpmndi:BPMNShape bpmnElement="approveInvoice" id="BPMNShape_b54e1244-b4fb-4e70-8c0d-4b76eb2798b0"> <dc:Bounds height="80.0" width="100.0" x="336.0" y="78.0"/> </bpmndi:BPMNShape> <bpmndi:BPMNEdge bpmnElement="sequenceFlow_57a81fcd-fb35-42cd-afca-7c4c7914936d" id="BPMNEdge_dfa41f0e-273b-4d62-b8b8-ef9286b24f7d"> <di:waypoint x="286.0" y="118.0"/> <di:waypoint x="336.0" y="118.0"/> </bpmndi:BPMNEdge> <bpmndi:BPMNShape bpmnElement="exclusiveGateway_b66a0444-2889-4cae-ac78-c1f65405ba0b" id="BPMNShape_bc1af4c3-ef1f-4c26-a42c-b1c2982bf35c" isMarkerVisible="true"> <dc:Bounds height="50.0" width="50.0" x="486.0" y="93.0"/> </bpmndi:BPMNShape> <bpmndi:BPMNEdge bpmnElement="sequenceFlow_1fe15a36-427e-4000-8fc7-50b8925ea1e5" id="BPMNEdge_9e81a730-2822-4c70-8061-9bbecf05022d"> <di:waypoint x="436.0" y="118.0"/> <di:waypoint x="486.0" y="118.0"/> </bpmndi:BPMNEdge> <bpmndi:BPMNShape bpmnElement="userTask_79a63b4f-96a7-43d7-aab3-e8e0e83769e5" id="BPMNShape_8c455164-1097-43ca-814f-6d601735b27a"> <dc:Bounds height="80.0" width="100.0" x="586.0" y="78.0"/> </bpmndi:BPMNShape> <bpmndi:BPMNEdge bpmnElement="sequenceFlow_9156c1d4-f756-447b-a384-e3bf17c43ff4" id="BPMNEdge_47ba6c2b-fd10-4faf-8ee9-cbe019282080"> <di:waypoint x="536.0" y="118.0"/> <di:waypoint x="586.0" y="118.0"/> </bpmndi:BPMNEdge> <bpmndi:BPMNShape bpmnElement="serviceTask_9d976f99-f8fb-4705-ae6d-a606758111f4" id="BPMNShape_d2e257f4-4c63-44e6-a8ab-d3179a83682c"> <dc:Bounds height="80.0" width="100.0" x="736.0" y="78.0"/> </bpmndi:BPMNShape> <bpmndi:BPMNEdge bpmnElement="sequenceFlow_b82e04ab-a0cc-4969-989a-1ec64d74d990" id="BPMNEdge_e5727f31-71a0-4f03-8a9d-7aca2cd9999a"> <di:waypoint x="686.0" y="118.0"/> <di:waypoint x="736.0" y="118.0"/> </bpmndi:BPMNEdge> <bpmndi:BPMNShape bpmnElement="endEvent_affc9949-819a-4b79-98bd-0f2fd844d014" id="BPMNShape_4a1b2f6f-6929-4fd7-b6cf-9f49410242d7"> <dc:Bounds height="36.0" width="36.0" x="886.0" y="100.0"/> </bpmndi:BPMNShape> <bpmndi:BPMNEdge bpmnElement="sequenceFlow_f0f99688-25b1-417e-9a5d-0d17503cb3ba" id="BPMNEdge_28346c07-6da9-41d2-bcf2-76a9583ea933"> <di:waypoint x="836.0" y="118.0"/> <di:waypoint x="886.0" y="118.0"/> </bpmndi:BPMNEdge> <bpmndi:BPMNShape bpmnElement="userTask_7b955191-5741-44df-b7ba-d154ddfbe616" id="BPMNShape_1c62b32d-2c17-48b0-bbc7-ac0074c97e62"> <dc:Bounds height="80.0" width="100.0" x="586.0" y="208.0"/> </bpmndi:BPMNShape> <bpmndi:BPMNEdge bpmnElement="sequenceFlow_29bab2ba-6108-4731-94c3-93a6955d1946" id="BPMNEdge_40c826c8-638d-4cd2-b9a1-ccdfa9a5ee6e"> <di:waypoint x="511.0" y="143.0"/> <di:waypoint x="511.0" y="248.0"/> <di:waypoint x="586.0" y="248.0"/> </bpmndi:BPMNEdge> <bpmndi:BPMNShape bpmnElement="exclusiveGateway_5aa645c5-a5e7-4453-8498-8462092b85b1" id="BPMNShape_36d66f18-3b46-4fde-9342-3ccd8d0f838d" isMarkerVisible="true"> <dc:Bounds height="50.0" width="50.0" x="736.0" y="223.0"/> </bpmndi:BPMNShape> <bpmndi:BPMNEdge bpmnElement="sequenceFlow_74d95e16-7907-4000-9ffb-cdba8c3ddde4" id="BPMNEdge_257a94d2-a5f6-4a88-9503-f5b9fd65cc7e"> <di:waypoint x="686.0" y="248.0"/> <di:waypoint x="736.0" y="248.0"/> </bpmndi:BPMNEdge> <bpmndi:BPMNShape bpmnElement="endEvent_68057c88-fa46-43cc-a93c-774b26be7b50" id="BPMNShape_2dff264a-5f15-44d9-ba38-b962be76ea74"> <dc:Bounds height="36.0" width="36.0" x="836.0" y="230.0"/> </bpmndi:BPMNShape> <bpmndi:BPMNEdge bpmnElement="sequenceFlow_3bf21b37-c534-4541-b84f-03d3fe05c989" id="BPMNEdge_0a149725-d17c-4b6f-b7db-7854d0a27b00"> <di:waypoint x="786.0" y="248.0"/> <di:waypoint x="836.0" y="248.0"/> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="sequenceFlow_6987bcb8-5f6a-467b-9b25-e21b90dd0d4d" id="BPMNEdge_8b25f14c-9653-42ab-a57f-48fc07bd7ee8"> <di:waypoint x="761.0" y="273.0"/> <di:waypoint x="761.0" y="118.0"/> <di:waypoint x="336.0" y="118.0"/> </bpmndi:BPMNEdge> </bpmndi:BPMNPlane> </bpmndi:BPMNDiagram> </definitions> 元素。

© www.soinside.com 2019 - 2024. All rights reserved.