Java - Camunda BPMN 模型 API : how to save valid xml?

标签 java xml bpmn camunda camunda-modeler

我正在构建一些测试 BPMN 2.0 模型并将它们保存到 xml 文件,在一个 Java 项目中,按照官方提供的示例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 应用程序和 bpmn.io 显示 BPMN 时,生成的 xml 似乎无效。 .

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

最佳答案

我终于通过切换到流畅的模型构建器 API 使其工作,遵循这个 https://blog.camunda.com/post/2014/02/the-new-camunda-bpmn-model-api/

这是我更新的测试类:

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>

通过与上面的 xml 进行比较,我注意到一些新的 <bpmndi ...>之前不存在的元素。

关于Java - Camunda BPMN 模型 API : how to save valid xml?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53634916/

相关文章:

java - 如何从 Android 的 ListView 中删除项目?有像iOS那样的内置控件吗?

java - 无法使 Batik 中的 JSVGCanvas 在 Maven 项目中工作

java - 从 pom.xml 中删除 -SNAPSHOT

c++ - Poco 从字节缓冲区解析 XML 文档

java - 将 Eclipse 插件添加到 Eclipse RCP App

mysql - Activiti mysql 性能调优(索引)

java - "Bpmn2 Diagram Editor"和 "BPMN2 Process Editor"之间的区别

java - JPA : removing from a collection 中管理双向关系时出现问题

html - 为什么在从 Docbook/Oxygen 生成的 html 文件中不显示斜体文本

android - 如何从 XML 中获取嵌入的 XML