examples

Contents

Features by Examples

Service Task

In Process definition (.bpmn file), use implementation attribute to define name of JavaScript/TypeScript Method to perform the Task:

![Using Modeler](./images/bb-service.PNG)

“`xml
<servicetask id="serviceTask" name="Service Task" implementation="service1">

</servicetask>
“`

“`ts
class AppServices {

async service1(item,input) {
seq++;
await delay(3000 -(seq * 100) , 'test');
item.log("SERVICE 1" + item.token.currentNode.id);
}
}

“`

Script Task

![Using Modeler](images/bb-script.PNG)

“`xml
<scripttask id="Activity_06typtl" name="script" scriptformat="JavaScript">
<script>

this.log('testing from <testing> the inside: '+data.loopKey);
</script>
..
</scripttask>
“`

Conditional Flow

![Using Modeler](images/bb-conditional-flow.PNG)

“`xml

<sequenceflow>

<conditionexpression xsi:type="bpmn:tFormalExpression" language="JavaScript">
(data.needsCleaning=="Yes")
</conditionexpression>
..

“`

Form Input Fields

![Using Modeler](images/bb-form.PNG)

“`xml
<usertask id="task_Buy" name="Buy">
<extensionelements>
<formdata>
<formfield id="needsRepairs" label="Repairs Required?" type="boolean"></formfield>
<formfield id="needsCleaning" label="Cleaning Required?" type="boolean"></formfield>
</formdata>
</extensionelements>

</usertask>

“`

Multiple Start Event

![Image description](examples/invoice-start.png)

When a definition/process has multiple start node, you need to specify the start node when starting the process:

From the Web UI:

![Image description](examples/invoice-start-prompt.png)

From API:
“`ts

response = await api.engine.start('invoice',
{ reminderCounter: 0, caseId: caseId}, user, {startNodeId:'StartEvent_AP'});
“`

Business Rule Task

BPMN-Server supports Business Rules implemented through DMN-Engine
Business Rules can be defined as a Decision Table as in this example:

Vacation Decision Table

Decision Table is called through

    <bpmn2:businessRuleTask id="Task_1lcamp6" name="Vacation"  camunda:decisionRef="Vacation">

This will load the file ‘Vacation.json’ form the Processes folder as defined in configuration.js

Script Extensions

Scripts can be added to listen to two events:

  • Start before the Task is executed
  • End after the task is executed

![Using Modeler](images/bb-event-scripts.PNG)

In this example we are adding a script to bpmn:startEvent

“`xml
<extensionelements>
<executionlistener event="start">
<script scriptformat="JavaScript">

console.log("This is the start event");
data.records=[1,2,3];
console.log(data);

</script>
</executionlistener>
<executionlistener event="end">
<script scriptformat="JavaScript">

console.log("This is the end event");

</script>
</executionlistener>
</extensionelements>

“`

Timer Event

![Using Modeler](images/bb-timer.PNG)

“`xml
<intermediatecatchevent id="Event_timer">
<incoming>Flow_1sg7v2d</incoming>
<outgoing>Flow_1nku8og</outgoing>
<timereventdefinition id="TimerEventDefinition_07xu06a">
<timeduration xsi:type="bpmn:tExpression">PT2S</timeduration>
</timereventdefinition>
</intermediatecatchevent>
“`
More on [timers](timers.md)

Multi-instances Tasks

![Using Modeler](images/bb-multi-instance.PNG)

“`xml
<scripttask id="scriptTask" name="Script Task">
<incoming>Flow_159xzcz</incoming>
<outgoing>Flow_0t7z2os</outgoing>
<multiinstanceloopcharacteristics issequential="true" camunda:collection="$(data.records)"></multiinstanceloopcharacteristics>
<script><![CDATA[this.log('testing from the inside: '+data.loopKey);]]></script>
</scripttask>
“`
For Multi-instance data handling [see](data.md)

Call Process

![Using Modeler](images/bb-call.PNG)

“`xml
<callactivity id="activity_call" name="Call Task" calledelement="loop">

</callactivity>

“`
In the above example ‘loop’ is the name of process to be called.

Throwing and Cathcing Messages

In this example, we will demonstrate how can two seperate processes communicate through “Messages”

Using Modeler

1 Throw a message with data

When a process throw a message, bpmn-server checks if there is another process that can catch this message before dispatching it to AppDelegate.

    <bpmn2:intermediateThrowEvent id="throw_msg1" name="msg1">
      <bpmn2:messageEventDefinition id="messageEventDef1" messageRef="Msg1" />
      <bpmn2:extensionElements>
        <camunda:script event="start"><![CDATA[
        input.caseId= data.caseId;
        this.messageMatchingKey={'data.caseId': data.caseId };
        ]]></camunda:script>
      </bpmn2:extensionElements>
      ...
    </bpmn2:intermediateThrowEvent>

The above will through a messsage as follows:

  • Message Id: Msg1
  • Message Output: caseId: <someValue>

2 Catch a message with data

The second process defines a start event to catch the message Msg1

    <bpmn2:startEvent id="StartEvent_1w66wpl" name="msg1">
      ...
      <bpmn2:messageEventDefinition id="messageEventDef4" messageRef="Msg1" />
    </bpmn2:startEvent>

Therefore, the system will create a new instance of the second process and assign the Message output data, namely, the caseId

3 Throw a message with data and a Key

In addition, the second process sends a confirmation message Confirm1 to the first process

    <bpmn2:intermediateThrowEvent id="throw_confirm1" name="confirm1">
      <bpmn2:messageEventDefinition id="messageEventDef2" messageRef="Confirm1" />
      <bpmn2:extensionElements>
        <camunda:script event="transformOutput"><![CDATA[

        this.output.confirm=true;
        this.context.messageMatchingKey={'data.caseId': this.token.data.caseId };

        ]]></camunda:script>
      </bpmn2:extensionElements>
        ...
    </bpmn2:intermediateThrowEvent>

Howerver, the challenge here is that make sure the message is sent to the specific instance, that is where the Matching key is used

  • Message Id: Confirm1
  • Message Output: confirm: true
  • Message Matching Keyt: ‘data.caseId’: this.token.data.caseId
Image description

Input and Output Data Handling

this for details

Gateway

Event Based Gateway

Boundary Events

UserTask Assignment