BPMN export
Business Process Model and Notation (BPMN) is a graphical representation for specifying business processes in a business process model. Along with the BPMN specification, an XML schema is also defined that allows a BPMN diagram to be exported to XML.
JointJS+ provides a BPMN export plugin that enables the export process within the JointJS+ framework.
Installation
The BPMN export plugin is an independent module distributed as part of the JointJS+ archive:
- Unzip the archive and navigate to the
build/package-bpmn-export
folder inside. - Copy the
joint-bpmn-export.tgz
file and paste it into the root of your package.
Then, install the BPMN export package (@joint/format-bpmn-export
) using your package manager:
- npm
- pnpm
- yarn
npm add joint-bpmn-export.tgz
pnpm add ./joint-bpmn-export.tgz
yarn add @joint/format-bpmn-export@file:joint-bpmn-export.tgz
Now, you can import functionality from @joint/format-bpmn-export
into your application as necessary:
import { toBPMN } from '@joint/format-bpmn-export';
const exportResult = toBPMN(paper);
There is also a UMD version available
Place the UMD distribution of the plugin into the root of your package:
- Navigate to the
build/package-bpmn-export/dist
folder inside the unzipped JointJS+ archive. - Copy the
joint.format.bpmnExport.js
file and paste it into the root of your package.
Include joint.format.bpmnExport.js
in your HTML:
- JointJS
- JointJS+
<script src="joint.js"></script>
<script src="joint.format.bpmnExport.js"></script>
Access toBPMN
through the joint.format
namespace:
const exportResult = joint.format.toBPMN(paper);
Architecture and API explained
There are only a few core concepts to understand when working with this package.
toBPMN(paper, options = {})
This function handles the export process. It takes a joint.dia.Paper
containing a diagram and optionally the options
object. The inclusion of the parameter provides the flexibility to customize the export process to meet specific requirements.
Export options object
It is an object with the following properties:
exportableObjectFactories
A collection of exportable object factories mapped by shape types.
Each exportable object factory is a function that gets a cell view as a parameter, and is expected to create and return
an exportable object, or null
, if the processed element should be completely excluded from the export.
Exportable objects
If the export engine worked directly with joint.shapes.bpmn2
, there would be little room for customization. That's
why the concept of exportable objects comes into play.
In the first step, each cell in the diagram is converted into a corresponding exportable object that encapsulates all the information necessary for subsequent serialization into the desired XML fragments. And then, in the next step, the engine gets the XML fragments generated and assembles them all into the final XML result.
This concept introduces a high degree of flexibility. In particular, there's no requirement to use only shapes
from joint.shapes.bpmn2
. In essence, any entity that can be transformed into a corresponding exportable object can
be seamlessly integrated into the process. This allows working with custom shape implementations for selected BPMN
elements. Alternatively, shapes from joint.shapes.bpmn2
can be used, but their processing can be further customized.
These ideas will be further explored and elaborated in the following examples.
The engine recognizes the following exportable objects, and their properties and methods:
Activity
type: string
markers: string[]
label: string | null
constructor(cellView: dia.CellView, type: string, markers: string[], label?: string)
toTaskXMLElement(): Element
toShapeXMLElement(): Element
Flow
label: string | null
type: string | null
constructor(cellView: dia.CellView, label?: string, type?: string)
toFlowXMLElement(): Element
toEdgeXMLElement(): Element
Event
type: string
marker: string | null
interrupting: boolean | null
label: string | null
constructor(
cellView: dia.CellView,
type: string,
marker?: string,
interrupting?: boolean,
label?: string
)
toEventXMLElement(): Element
toShapeXMLElement(): Element
Gateway
type: string | null
label: string | null
constructor(cellView: dia.CellView, type?: string, label?: string)
toGatewayXMLElement(): Element
toShapeXMLElement(): Element
DataAssociation
constructor(cellView: dia.CellView)
toEdgeXMLElement(): Element
Annotation
text: string | null
constructor(cellView: dia.CellView, text?: string)
toTextAnnotationXMLElement(): Element
toShapeXMLElement(): Element
AnnotationLink
constructor(cellView: dia.CellView)
toAssociationXMLElement(): Element
toEdgeXMLElement(): Element
Group
label: string | null
constructor(cellView: dia.CellView, label?: string)
toCategoryXMLElement(): Element
toGroupXMLElement(): Element
toShapeXMLElement(): Element
Pool
lanes: Lane[]
header: string | null
constructor(cellView: dia.CellView, lanes: Lane[], header?: string)
toProcessXMLElement(): Element
toParticipantXMLElement(): Element
toShapeXMLElement(): Element
DataObject
label: string | null
constructor(cellView: dia.CellView, label?: string)
toDataObjectXMLElement(): Element
toDataObjectReferenceXMLElement(): Element
toShapeXMLElement(): Element
Lane (Interface)
id: string
fullyQualifiedId: string
label: string | null
sublanes: Lane[]
Exportable object factories
There must be something that can convert a BPMN shape element (one from joint.shapes.bpmn2
or a custom one) into a
corresponding exportable object. This piece of the puzzle is called an exportable object factory. It's essentially a
function designed to create a specific exportable object from a given BPMN shape element.
Each shape element is intended to be processed by a dedicated factory, and this factory can be either one of the default factories or a completely custom implementation.
There is a set of predefined default factories that cover the shapes from joint.shapes.bpmn2
. However, any of these
defaults can be overridden in the export options object using the exportableObjectFactories
property. This flexibility
allows users to customize the exportable object creation process to their specific needs and requirements.
When implementing a custom exportable object factory, the exportable object can either be created from scratch, or the
default factory (if one exists for the cell type being processed) can be used to create an object base, and then further
customization can be performed. If the default factory exists, it is passed as a second parameter called defaultFactory
,
which can be invoked.
Examples
Basic usage
The most basic way to use the package is to convert a paper with a diagram to XML without using an options
parameter.
It's as simple as calling toBPMN
with the paper
as a parameter.
const exportResult = toBPMN(paper);
// exportResult.cells instanceof XMLDocument
Usage with custom exportable object factories and built-in shapes
Sometimes only a subtle adjustment is needed in the XML result. For example, when using the bpmn2.Event
shape, and
the desire is to have the label in uppercase in the XML result.
In such case, the solution is to refine the value of the label
property within the corresponding exportable object.
This customization can be done in a custom exportable object factory registered for the bpmn2.Event
element type.
Once implemented, the resulting XML fragment will display the label in uppercase.
const exportResult = toBPMN(paper, {
exportableObjectFactories: {
'bpmn2.Event': (cellView, defaultFactory) => {
const exportableObject = defaultFactory();
exportableObject.label = exportableObject.label.toUpperCase();
return exportableObject;
}
}
});
Usage with custom exportable object factories and custom shapes
Sometimes the shapes available in joint.shapes.bpmn2
may not cover all the needs of a project. In such case, it is
necessary to define custom shapes. To include these custom shapes in the export process, it is further necessary to
define custom exportable object factories. Each of these factories is responsible for converting a specific custom shape
into the corresponding exportable object.
const CustomShape = joint.shapes.bpmn2.Activity.define(
'CustomShape'
);
const customShape = new CustomShape({
position: {
x: 10,
y: 10,
},
attrs: {
label: {
text: 'Custom shape'
}
}
});
paper.model.addCell(customShape);
exportResult = toBPMN(paper, {
exportableObjectFactories: {
'CustomShape': (cellView, defaultFactory) => {
return new exportableObjects.Activity(cellView, 'task', [], cellView.model.attr('label/text'));
}
}
});
Usage with custom exportable object factories, built-in shapes and extended exportable object
Another way to customize the export process is to extend the predefined exportable objects.
There is an extensionElement
element defined in BPMN XML that allows the embedding of custom, BPMN-independent information.
Each exportable object contains methods that return XML fragments, and the creation of these fragments can be fully
customized. In the following example, the creation of the process element is extended by generating an additional
extensionElement
with a nested myCustomInformation
element from a non-BPMN namespace.
class CustomExportableActivity extends exportableObjects.Activity {
toTaskXMLElement() {
const taskXMLElement = super.toTaskXMLElement();
const exampleNamespace = 'http://www.example.org';
taskXMLElement.setAttribute('xmlns:example', exampleNamespace);
const extensionElements = document.createElementNS('http://www.omg.org/spec/BPMN/20100524/MODEL', 'extensionElements');
extensionElements.appendChild(document.createElementNS(exampleNamespace, 'example:myCustomInformation'));
taskXMLElement.appendChild(extensionElements)
return taskXMLElement;
}
}
exportResult = toBPMN(paper, {
exportableObjectFactories: {
'bpmn2.Activity': (cellView, defaultFactory) => {
const exportableObject = defaultFactory();
return new CustomExportableActivity(
cellView,
exportableObject.type,
exportableObject.markers,
exportableObject.label
);
}
}
});
Coverage of the BPMN 2 domain
The BPMN 2 domain is large and the export plugin doesn't cover it all yet.
List of supported elements
- Tasks
- Task
- Service Task
- Send Task
- Receive Task
- User Task
- Manual Task
- Business Rule Task
- Script Task
- Subprocesses
- Events
- Start Event
- Intermediate Throw Event
- Intermediate Catch Event
- Boundary Event
- End Event
- Gateways
- Gateway
- Parallel Gateway
- Inclusive Gateway
- Complex Gateway
- Event Based Gateway
- Exclusive Gateway
- Sequence Flows
- Participants
- Pool
- Swimlane
- Message Flows
- Data Objects
- Data Object
- Data Input Association
- Data Input Association
- Data Output Association
- Text Annotations
- Associations
List of elements to be supported in the future
- Conversations
- Conversation Links
- Choreography