This is a use case example of using the CamundaBPM (Camunda.org) Model API with Vertx. Allows you to provide a BPMN file which will be read and parsed by Camunda's Java Model API and then rendered through a provided FreeMarker template.
This lets you provide a FreeMarker template and a BPMN file; the output is a rendered template. The purpose is to allow someone to navigate the Camunda BPMN model API directly in the FreeMarker template in order to easily generate documentation for BPMN files.
Install NPM Dependencies: ./gradlew clean npmInstall
Run Gradle Build: ./gradlew clean run
- https://docs.camunda.org/javadoc/camunda-bpm-platform/7.8/?org/camunda/bpm/model/bpmn/instance/package-summary.html
- User Tasks Model Element: https://docs.camunda.org/javadoc/camunda-bpm-platform/7.8/org/camunda/bpm/model/bpmn/instance/UserTask.html
...
<bpmn:userTask id="Task_0w364uq" name="Step 3" camunda:assignee="chris">
<bpmn:extensionElements>
<camunda:properties>
<camunda:property name="order" value="My Order" />
<camunda:property name="title" value="My Title" />
<camunda:property name="failure" value="My Failure" />
<camunda:property name="resolution" value="My Resolution" />
</camunda:properties>
</bpmn:extensionElements>
<bpmn:incoming>SequenceFlow_0adri7o</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_15kfmnc</bpmn:outgoing>
</bpmn:userTask>
...
template is loaded from app/templates/myTemplate.ftl
Example:
<#list tasks_>
Elements:
<#items as task>
Task Type:
${task.getElementType().getTypeName()}
Task Name:
${task.getName()}
Custom Attributes:
<#list task.getExtensionElements().getElementsQuery().filterByType(extensionElements_).singleResult().getCamundaProperties()>
<#items as extensionElement>
Attribute:
Key: ${extensionElement.getCamundaName()}
Value: ${extensionElement.getCamundaValue()}
</#items>
</#list>
--------------------
</#items>
</#list>
The template_inputs property is inserted into freemarker. Any property with a underscore _
at the end of the property name will go through eval()
.
Config is loaded from app/template_config.json
...
{
"template_inputs": {
"extensionElements_": "instanceClass('camunda.CamundaProperties')",
"tasks_": "modelInstance.getModelElementsByType(instanceClass('Task'))"
},
"template_path": "myTemplate.ftl"
}
...
The extensionElements_
property is a special property that provides the CamundaProperties Class for use in the FreeMarker template such as:
<#list task.getExtensionElements().getElementsQuery().filterByType(extensionElements_).singleResult().getCamundaProperties()>
Elements:
Task Type:
userTask
Task Name:
Step 1
Custom Attributes:
Attribute:
Key: order
Value: some order value
Attribute:
Key: title
Value: some title value
Attribute:
Key: failure
Value: some fail
Attribute:
Key: resolution
Value: some resolution
--------------------
Task Type:
userTask
Task Name:
Step 2
Custom Attributes:
Attribute:
Key: order
Value: order123
Attribute:
Key: title
Value: title321
Attribute:
Key: failure
Value: fail000
Attribute:
Key: resolution
Value: resABC
--------------------
Task Type:
userTask
Task Name:
Step 3
Custom Attributes:
Attribute:
Key: order
Value: My Order
Attribute:
Key: title
Value: My Title
Attribute:
Key: failure
Value: My Failure
Attribute:
Key: resolution
Value: My Resolution
--------------------
Provide external / injectableinput
object as a json file.Config/Input defines the Template- Provide a File Writer
- Add more generation get Elements call so that all elements are gotten and the FreeMarker template will sub-navigate the tree of elements. (Removes the current need to setup "Per Element Type" properties in the
inputs
object) - Provide a HTTP endpoint to get the rendered template as different content types such as JSON and HTML
- Provide a HTTP Endpoint to inject Config and FTL templates so the parser can live as a "microservice"
- Generate Image of BPMN file
- Generate Zoomed in Image of BPMN Element in context of overall file