Scripting Everywhere in camunda BPM

By
  • Blog
  • >
  • Scripting Everywhere in camunda BPM
TOPICS

30 Day Free Trial

Bring together legacy systems, RPA bots, microservices and more with Camunda

Sign Up for Camunda Content

Get the latest on Camunda features, events, top trends, and more.

TRENDING CONTENT
With the last camunda BPM 7.2.0-alpha3 release we heavily extended the scripting support of the camunda BPM platform. We started to improve scripting support with the 7.2.0-alpha1 release and now we think we are done. It is now your turn to start using the different scripting languages and help us to polish this feature for our final release. To get an detailed overview of the scripting support please visit our user guide.

 

Where can I use scripts?

Everywhere but to be more specific you can use scripts as:
  • Script tasks (of course)
  • Execution listener
  • Task listener
  • Condition of sequence flows
  • Input output mapping (added in 7.2.0-alpha2)
The implementation of the scripting support in camunda BPM is designed to be independent from BPMN which will allow us to also support scripting in our new CMMN implementation right from the beginning.

Why should I use scripts?

First of all scripting is fun. But besides that there are also more convincing reasons to use scripting in camunda BPM.
 
With the extended scripting support it is easy to prototype complete processes including the business logic. Also the sharing of such prototypes is simple, because the whole code can be embedded inside the process. So only one file has to be exchanged and discussed. In combination with the BPMN model API it allows you to create mock processes with business logic directly inside your code.
 
Another advantage is that now also non-Java programmers can use camunda BPM to execute their processes without writing Java code. Or if you already have an non-Java code base you can now use it inside camunda BPM without porting it to Java.
 
We also allow you to reuse scripts by using the camunda:resource attribute. Which loads scripts from external resources. Either the scripts can be part of your deployment or reside in the classpath of your application. To get more information on this please see the corresponding section in the user guide.
 

Let there be scripts

To demonstrate the new feature I created a small example process without a single line of Java code. The following process simulates a dice game in a casino.

example process simulating dice games

The first process element is a script task which should welcome the new player.
 
<bpmn2:scriptTask id="scriptTask" name="Welcome Message" scriptFormat="groovy">
  <bpmn2:extensionElements>
    <camunda:inputOutput>
      <camunda:inputParameter name="player">

        <!-- script as input parameter -->
        <camunda:script scriptFormat="groovy">
          players = ["Fritz", "Heinz", "Horst", "Klaus"]
          players[new Random().nextInt(players.size())]
        </camunda:script>

      </camunda:inputParameter>
    </camunda:inputOutput>
  </bpmn2:extensionElements>

  <!-- script as script task -->
  <bpmn2:script>
    println "Hello $player! Welcome to our casino"
  </bpmn2:script>
</bpmn2:scriptTask>

We use a input parameter mapping to randomly select our new player. Therefore a groovy script is evaluated and the result of the last script line is saved to the local variable player. Inside the script task than another groovy script just welcomes the newly select player with a kind message.

At the start of the exclusive gateway we roll the dice. To do so we use an execution listener for the start event of the gateway.

<bpmn2:exclusiveGateway id="gateway" name="Dice">
  <bpmn2:extensionElements>
    <camunda:executionListener event="start">

      <!-- script as execution listener -->
      <camunda:script scriptFormat="groovy">
        aNumber = new Random().nextInt(6) + 1
        println "$aNumber was diced"
        execution.setVariable('aNumber', aNumber)
      </camunda:script>

    </camunda:executionListener>
  </bpmn2:extensionElements>
</bpmn2:exclusiveGateway>

The execution listener is another script which saves the result as a process variable so it can be used to evaluate the following sequence flow conditions. The variable is set with the help of the execution variable which corresponds to the DelegateExecution interface.  

The conditions of the sequence flow could be expression language but this is a blog post about scripting so lets use a script for that.

<bpmn2:sequenceFlow id="flow3" name="Greater than 3" sourceRef="gateway" targetRef="userTaskPlayerWins">
  <!-- script as sequence flow condition -->
  <bpmn2:conditionExpression xsi:type="bpmn2:tFormalExpression" language="groovy">
    aNumber > 3
  </bpmn2:conditionExpression>
</bpmn2:sequenceFlow>
<bpmn2:sequenceFlow id="flow4" name="Less then 4" sourceRef="gateway" targetRef="userTaskBankWins">
  <!-- script as sequence flow condition -->
  <bpmn2:conditionExpression xsi:type="bpmn2:tFormalExpression" language="groovy">
    <![CDATA[
      aNumber < 4
    ]]>
  </bpmn2:conditionExpression>
</bpmn2:sequenceFlow>

Both groovy scripts just evaluate the process variable set by the exclusive gateway.  

The last action is to inform the system which user task should be executed. For that we add a task listener to both user tasks for the create event.

<bpmn2:userTask id="userTaskBankWins" name="Bank Wins">
  <bpmn2:extensionElements>
    <camunda:taskListener event="create">
 
      <!-- script as task listener -->
      <camunda:script scriptFormat="groovy">
        println "User task '$task.name' was $task.eventName"
      </camunda:script>
 
    </camunda:taskListener>
  </bpmn2:extensionElements>
</bpmn2:userTask>
<bpmn2:userTask id="userTaskPlayerWins" name="Player Wins">
  <bpmn2:extensionElements>
    <camunda:taskListener event="create">

      <!-- script as task listener -->
      <camunda:script scriptFormat="groovy">
        println "User task '$task.name' was $task.eventName"
      </camunda:script>

    </camunda:taskListener>
  </bpmn2:extensionElements>
</bpmn2:userTask>

The task listeners are again groovy scripts which uses the task variable to print the task name and the event. The task variable corresponds to the DelegateTask interface.  

So that’s it. A whole process without a single line of Java code. To see the complete BPMN xml have a look at this gist. Or if you want directly start playing with it you can clone a test project here.  

Now it’s your turn. Have fun and start scripting. And if you have any remarks our if you miss a features please let us know.

Camunda Developer Community

Join Camunda’s global community of developers sharing code, advice, and meaningful experiences

Try All Features of Camunda

Related Content

We're streamlining Camunda product APIs, working towards a single REST API for many components, simplifying the learning curve and making installation easier.
Learn about our approach to migration from Camunda 7 to Camunda 8, and how we can help you achieve it as quickly and effectively as possible.
We've been working hard to reduce the job activation latency in Zeebe. Read on to take a peek under the hood at how we went about it and then verified success.