Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

BPMN2-Modeler/DeveloperTutorials/ModelExtension

< BPMN2-Modeler‎ | DeveloperTutorials
Revision as of 10:30, 12 March 2015 by Bbrodt.redhat.com (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Versions

This Tutorial was developed with Eclipse 4.4 (Luna) and BPMN2-Plugin version 1.1.1.

Model Extension: what is it, and why do I need it?

There are only two possible reasons for wanting to build a BPMN2 Modeler extension plugin that we can think of:

  1. We need a graphical tool that can build BPMN 2.0 compliant, executable process files for a particular BPM execution engine.
  2. We would like to use a graphical tool for documenting our business processes, but the BPMN 2.0 spec is insufficient for defining some particular piece of information that our business requires.

In both cases, you will likely need to extend the BPMN 2.0 language with your engine, or business-specific XML attributes and elements. In some cases you may even want to limit what is presented by the editor if you only need a small subset of BPMN 2.0, but this is a topic for another tutorial.

The BPMN2 Modeler extension API offers several different methods of extending the BPMN2 model, and each addresses a particular use-case as discussed next.

The <modelExtension> extension point

The BPMN2 Modeler core exposes the org.eclipse.bpmn2.modeler.core.org.eclipse.bpmn2.modeler.runtime plugin extension point. One of these extension elements is called "modelExtension". Please see the Core Extension Point API documentation for details.

This is used if you simply need to "decorate" a specific BPMN2 type with your own, business-specific attributes and elements, e.g. a UserTask or SequenceFlow. The jBPM extension plugin demonstrates a perfect example of when to use this extension:

    <modelExtension
        id="org.eclipse.bpmn2.modeler.runtime.jboss.jbpm5.modelExtension.sequenceFlow"
        runtimeId="org.jboss.runtime.jbpm5"
        name="%modelExtension.name.0"
        type="SequenceFlow">
        <property name="priority" value="1"/>
        <property name="name" value=""/>
    </modelExtension>

Here the type identifies a BPMN2 model type to which this extension applies, in this case a SequenceFlow. Note that we do not use the fully qualified "org.eclipse.bpmn2.SequenceFlow" class name because modelExtension is limited to only BPMN2 model objects and can not be used with external models.

This extension adds an attribute named priority to SequenceFlow; this attribute will be qualified with the "tns" prefix which corresponds to the targetNamespace "http://www.jboss.org/drools" defined by the jBPM plugin. The resulting XML looks like this:

    <bpmn2:sequenceFlow id="SequenceFlow_3" tns:priority="2" sourceRef="ExclusiveGateway_1" targetRef="Task_3"/>

As a bonus, this extension point is also used to override default initial values for existing BPMN2 attributes, and insert fully populated and initialized elements whenever a new BPMN2 object is created. Note that the name attribute in the example above is defined in the BPMN2 FlowElement. The default behavior of the editor is to automatically assign a generated name to all SequenceFlows, but the modelExtension example above initializes the name to an empty string.

A more complex example of this initialization capability is demonstrated by the jBPM UserTask model extension (truncated here for simplicity):

    <modelExtension
        id="org.eclipse.bpmn2.modeler.runtime.jboss.jbpm5.modelExtension.userTask"
        runtimeId="org.jboss.runtime.jbpm5"
        name="%modelExtension.name.12"
        type="UserTask">
        
        <property name="ioSpecification">
            <value>
                <property name="outputSets">
                    <value>
                        <property name="name" value="Output Set" type="EString"/>
                    </value>
                </property>
                <property name="dataInputs">
                    <value>
                        <property name="name" value="TaskName" type="EString"/>
                    </value>
                </property>
                <property name="dataInputs">
                    <value>
                        <property name="name" value="Priority" type="EInt"/>
                    </value>
                </property>
                
                ...

                <property name="inputSets">
                    <value>
                        <property name="dataInputRefs" ref="ioSpecification/dataInputs#0"/>
                        <property name="dataInputRefs" ref="ioSpecification/dataInputs#1"/>
                        
                        ...
                        
                    </value>
                </property>
            </value>
        </property>
        <property name="dataInputAssociations">
            <value>
                <property name="assignment">
                    <value>
                        <property name="from" type="FormalExpression">
                            <value>
                                <property name="body" value="Task Name"/>
                            </value>
                        </property>
                        <property name="to" type="FormalExpression">
                            <value>
                                <property name="body" ref="ioSpecification/dataInputs#0"/>
                            </value>
                        </property>
                    </value>
                </property>
                <property name="targetRef" ref="ioSpecification/dataInputs#0"/>
            </value>
        </property>
        <property name="dataInputAssociations">
            <value>
                <property name="assignment">
                    <value>
                        <property name="from" type="FormalExpression">
                            <value>
                                <property name="body" value="1"/>
                            </value>
                        </property>
                        <property name="to" type="FormalExpression">
                            <value>
                                <property name="body" ref="ioSpecification/dataInputs#1"/>
                            </value>
                        </property>
                    </value>
                </property>
                <property name="targetRef" ref="ioSpecification/dataInputs#1"/>
            </value>
        </property>
        
        ...
        
    </modelExtension>

There's a lot of stuff going on here, let's go through each of these extension point elements:

  1. This modelExtension applies to the BPMN2 UserTask type.
  2. All BPMN2 Activity objects (Activity is a super class of UserTask) have an optional ioSpecification container which defines inputs to, and outputs from the Activity. The line <property name="ioSpecification"> will cause a new IoSpecification object to be created and attached to the UserTask.
  3. The lines that follow populate the IoSpecification object with OutputSet, DataInputs and InputSet objects each of which are, in turn, constructed and initialized
  4. Within the inputSets definition, this line: <property name="dataInputRefs" ref="ioSpecification/dataInputs#0"/> initializes the dataInputRefs of the InputSet object with a reference to the newly created DataInput object that has already been created and inserted into the IoSpecification object's dataInputs list at index 0.
  5. Similarly, the next line creates a reference to the DataInupt object at IoSpecification dataInputs list index 1.
  6. The remaining bits of this example function similarly to initialize the DataInputAssociations of the IoSpecification.

The <customTask> extension point

This extension is similar to modelExtension (i.e. it is used to extend and initialize a BPMN2 object) but is used only for objects that have a visual representation on the editing canvas. The name "customTask" is a misnomer because it can be used with not just Tasks, but any BPMN2 type that has a visual associated with it, for example SequenceFlow, EventDefinition, Gateway, etc.

The customTask definitions also appear in the tool palette as individual tool items in a tool drawer of your choosing. A Java class is required to manage the lifecycle of customTask objects. This class is involved in the Graphiti framework during creation, update and deletion so that every visual aspect of the element can be controlled.

For a detailed explanation of how to implement the Java code behind a customTask, see the Create a Custom Task tutorial.

BYOM! (bring your own model!)

Sometimes it becomes necessary to embed objects from an existing EMF model into a BPMN2 document. the BPMN 2.0 specification defines an extension mechanism using a special container element called (surprise!) "extensionElements". Feel free insert your application-specific model objects directly into this container, willy-nilly, without fear of breaking BPMN 2.0 compliance!

The very detailed tutorial Extending BPMN2 using an external EMF model shows you exactly how to do this, and provides some concrete examples.

Back to the top