The BPMN model API offers you a simple and straightforward way to interact with an BPMN 2.0 model. It enables you to gather information from an existing model, edit and extend them. Of course you can also create completely new ones.
Technically the model API is based on a DOM layer which is accessed and manipulated by a general XML API developed by us. On top of this, the BPMN model API encapsulates the interaction with the XML API. The BPMN model API as well as the XML API does not hold any state, which means only the DOM layer has the current model state. This enables us to read information which we currently are not aware of without the risk of losing such information. It also allows non-intrusive editing of BPMN Models, conserving custom formatting and source code comments.
In addition, if your BPMN 2.0 model contains custom elements or attributes they are always accessible even if they are not exposed through the high-level BPMN model Api. Although our BPMN model API cannot be aware of these custom extensions you can obtain and modify them easily with the generic XML API. Another benefit of this concept is that we can already show you the current state despite the fact that the current BPMN model API not yet implements all BPMN 2.0 elements. But the already supported elements are enough to create rather complex processes.
Show me some code please
Okey after all this promises I want to show you some code examples so you can get a first impression what already is possible with the BPMN model API.
public void testCreateProcess() {
modelInstance = Bpmn.createEmptyModel();
Definitions definitions = modelInstance.newInstance(Definitions.class);
definitions.setTargetNamespace("https://camunda.org/examples");
modelInstance.setDefinitions(definitions);
Process process = modelInstance.newInstance(Process.class);
definitions.addChildElement(process);
StartEvent startEvent = modelInstance.newInstance(StartEvent.class);
startEvent.setId("start");
process.addChildElement(startEvent);
UserTask userTask = modelInstance.newInstance(UserTask.class);
userTask.setId("task");
userTask.setName("User Task");
process.addChildElement(userTask);
SequenceFlow sequenceFlow = modelInstance.newInstance(SequenceFlow.class);
sequenceFlow.setId("flow1");
process.addChildElement(sequenceFlow);
connect(sequenceFlow, startEvent, userTask);
EndEvent endEvent = modelInstance.newInstance(EndEvent.class);
endEvent.setId("end");
process.addChildElement(endEvent);
sequenceFlow = modelInstance.newInstance(SequenceFlow.class);
sequenceFlow.setId("flow2");
process.addChildElement(sequenceFlow);
connect(sequenceFlow, userTask, endEvent);
Bpmn.writeModelToFile(new File("target/new-process.bpmn"), modelInstance);
}
connect(SequenceFlow flow, FlowNode from, FlowNode to) {
flow.setSource(from);
from.getOutgoing().add(flow);
flow.setTarget(to);
to.getIncoming().add(flow);
}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<definitions targetNamespace="https://camunda.org/examples" xmlns="https://www.omg.org/spec/BPMN/20100524/MODEL">
<process>
<startEvent id="start">
<outgoing>flow1</outgoing>
</startEvent>
<userTask id="task" name="User Task">
<incoming>flow1</incoming>
<outgoing>flow2</outgoing>
</userTask>
<sequenceFlow id="flow1" sourceRef="start" targetRef="task"/>
<endEvent id="end">
<incoming>flow2</incoming>
</endEvent>
<sequenceFlow id="flow2" sourceRef="task" targetRef="end"/>
</process>
</definitions>
Fluent model builder API
- process
- start event
- exclusive gateway
- parallel gateway
- script task
- service task
- user task
- end event
So lets create this process fully deployable on our camunda BPM platform in less then 50 lines of code. Please have a look at the complete code in our quickstart.
BpmnModelInstance modelInstance = Bpmn.createProcess()
.name("BPMN API Invoice Process")
.executable()
.startEvent()
.name("Invoice received")
.formKey("embedded:app:forms/start-form.html")
.userTask()
.name("Assign Approver")
.formKey("embedded:app:forms/assign-approver.html")
.assignee("demo")
.userTask()
.id("approveInvoice")
.name("Approve Invoice")
.formKey("embedded:app:forms/approve-invoice.html")
.assignee("${approver}")
.exclusiveGateway()
.name("Invoice approved?")
.gatewayDirection(GatewayDirection.Diverging)
.condition("yes", "${approved}")
.userTask()
.name("Prepare Bank Transfer")
.formKey("embedded:app:forms/prepare-bank-transfer.html")
.candidateGroups("accounting")
.serviceTask()
.name("Archive Invoice")
.className("org.camunda.bpm.example.invoice.service.ArchiveInvoiceService")
.endEvent()
.name("Invoice processed")
.moveToLastGateway()
.condition("no", "${!approved}")
.userTask()
.name("Review Invoice")
.formKey("embedded:app:forms/review-invoice.html" )
.assignee("demo")
.exclusiveGateway()
.name("Review successful?")
.gatewayDirection(GatewayDirection.Diverging)
.condition("no", "${!clarified}")
.endEvent()
.name("Invoice not processed")
.moveToLastGateway()
.condition("yes", "${clarified}")
.connectTo("approveInvoice")
.done();
Camunda Developer Community
Join Camunda’s global community of developers sharing code, advice, and meaningful experiences