What are you looking for?

Contributing to the Camunda Modeler and getting started with BPMN.io

  • Blog
  • >
  • Contributing to the Camunda Modeler and getting started with BPMN.io

A report from a true fan.

Watching sports is a little like using Open Source Software. I know that is a bit of a  stretch, but if you keep reading you will see that both need contribution from “hobby leagues”. By watching your favorite sports team you (maybe unintentionally) tell sports clubs and TV stations that you are interested in their offerings. Maybe at one point you decide to play the sport yourself. By starting to play, you begin contributing to that community. You may not ever be a professional athlete, but overall you start to influence the sport you’re participating in at a small level. 

I am a big user of bpmn.io. I guess if you work at Camunda that is inevitable. 

All Camunda frontend applications embed the bpmn.io libraries to render your BPMN, DMN and, in some rare cases, your CMMN diagrams. (Cockpit and Tasklist are used to access the workflow engine during runtime. Cockpit gives administrators an overview of the runtime of process instances and Tasklist allocates usertask to process participants. Optimize stores process data in its own database and allows users to generate reports and therefore provides analytics for processes.)

I am not just a user — I am a fan of the Camunda Modeler. The Camunda Modeler is a standalone desktop application that can be used to design your process and, more importantly, it helps you to prepare the process for implementation by providing a property panel. I like how fast I can model a process and how easy it is to find all BPMN symbols. From time to time I conducted BPMN workshops using other Modeling tools and, so far, nothing has converted me. When it comes to the design phase of processes within teams, Cawemo has closed the gap with their collaboration and documentation functionalities now as well. Maybe I am biased. But could you tell a FC Bayern fan to cheer for Borussia Dortmund? Probably not.

After more than four years watching the Modeler team release software, I decided it is time to get my keyboard and get involved. Obviously not in the professional league, but starting my own hobby league. How do you start to contribute to an open source software project, especially if the technology is not the one you are familiar with? For sure it is harder, but not impossible. 

For bpmn.io I discovered two starting points:

  1. Use the libraries to create your own Web Application, where you want to model or display a bpmn diagram, or
  2. Get started with the development of Camunda Modeler Plugins. I went for the second one

In the hobby league I always look for “getting-started” guides, tutorials and other code examples. Luckily there are plenty of Modeler PlugIns on GitHub available. There is a PlugIn example that can be used as a starting point. Another good starting point is to customize rules for the Modeler Linting Plugin. This Plugin helps you to analyze your BPMN diagrams for potential errors. The Plugin itself implements a basic set of rules based on the BPMN standard and Camunda’s Modeling best practices. Often organizations want to use their own rules depending on their use cases, which makes it handy that you can extend the rules.

I decided to implement a rule set that gives me a warning in the Camunda Modeler if a certain symbol is not supported by the Zeebe engine yet. I thought that might be useful if I want to migrate some processes from the Camunda Platform to Camunda Cloud in the future. In order to do this, I followed along with the recording from a workshop that Nico Rehwaldt, Project Lead for bpmn.io, gave at CamundaCon 2019 (you can watch the recordings and find the full tutorial in his GitHub repo). This tutorial was a huge help when I was taking my first steps into the world of bpmn.io.

By following this tutorial, I only needed to change a few things, such as querying a different BPMN symbol.  Here you can see what I did for the Sendtask:

/**
  * Rule that reports message send tasks being used.
  */
 module.exports = function() {
    function check(node, reporter) {
     if (is(node, 'bpmn:SendTask')) {
       reporter.report(node.id, 'Element is not yet supported by the Zeebe engine. Try to use a Service Task');
     }
   }
    return {
     check: check
   };
 };

In other cases, like for example escalation events, it was a little bit more complicated. First I had to remember the BPMN standard to see which kind of events can have escalation definitions. The BPMN escalation can be defined by a start event (inside an event subprocess) and intermediate throw event, a boundary event and an end event. 

So I am not querying for a single element but for multiple. Also I don’t want to see a warning if I am using any other event definition. By studying the node object, basically by printing it to the console, I learned more about the structure and how to access variables. Moreover you have to take into account that if you use a none start event the object structure will look different and the property “eventDefinition” won’t be there. So you have to take that into account to prevent getting an “undefined” error in your plugin.

/**
  * Rule that reports a compensation event being used.
  */
 module.exports = function() { 
    function check(node, reporter) {
    if (is(node, 'bpmn:BoundaryEvent') || is(node, 'bpmn:IntermediateThrowEvent') || is(node, 'bpmn:EndEvent')) {
     
     const eventType = node && node.eventDefinitions[0] ? node.eventDefinitions[0].$type : null;
     
       if(eventType === "bpmn:CompensateEventDefinition"){     
      
       reporter.report(node.id, 'Element is not yet supported by Zeebe Engine');
     }
   }   
    }  
   return {
     check: check
   };
  }

I enjoyed the fact that I could run my custom rules already in a dev mode and that the Modeler picked them up after refreshing it. It was certainly a new experience to see something visual right away. In case you want to try out the rules you can find them here and they will show you if certain symbols are not supported by Zeebe yet.

I went symbol by symbol. One of the last rules I implemented was a rule for the compensation event and the compensation maker. I applied it and refreshed my modeler. For a moment I was a little bit confused because the linting plugin showed an additional error based on its recommended rules. However there’s not actually an error in my model.

Model error

The yellow warning is my rule letting me know that Zeebe does not support the compensation event. However the red error saying “Element is not connected” is actually incorrect. Due to its special functionality of undoing a completed activity, a compensation boundary event and a compensation task are not allowed to be connected to a sequence flow. 

This is great! Even by playing in my “hobby league” I discovered that I can help in the “pro league.” Let’s look closer at the linting rule that created the error. The code can be found in the no-disconnect rule from the bpmnlint project: 

/**
* A rule that verifies that there exists no disconnected
* flow elements, i.e. elements without incoming
* _or_ outgoing sequence flows
*/
module.exports = function() {
 
 function check(node, reporter) {
 
   if (!isAny(node, ['bpmn:Task','bpmn:Gateway','bpmn:SubProcess','bpmn:Event']) || node.triggeredByEvent) {
     return;
   }
 
   const incoming = node.incoming || [];
   const outgoing = node.outgoing || [];
 
     
 if (!incoming.length && !outgoing.length) {
     reporter.report(node.id, 'Element is not connected');
   }
 }
  }
 
 return {
   check
 };
 
};

The rule actually checks for incoming and outgoing sequence flows at the BPMN elements. If there is no in- and outgoing sequence flow, it will create the error. The rule works as expected but now we want to change it so it won’t be triggered for attached compensation events and for compensation tasks. After getting familiar with the custom rules and the object structure of bpmn elements that seems doable. I created an extra check for the compensation task and for the boundary compensation event: 

 // Check for compensation boundary events
 
   if (node.$type == 'bpmn:BoundaryEvent') {
     var eventDefinitions = node.get('eventDefinitions');
     if (eventDefinitions.length == 1) {
       if (eventDefinitions[0].$type == 'bpmn:CompensateEventDefinition') {
         return;
       }
     }
   }
 
   // Check for compensation task
 
   if (node.isForCompensation) {
     return;
   }

By creating a PR and getting feedback, you can learn a lot. First you learn how to improve your code style. You’ll also get more familiar with how different teams handle contributions. In the case of bpmn.io you will also experience great support, even if your PR is not perfect. 

Even if you don’t find code to fix, don’t worry. My co-worker Rin Oliver explained that contribution does not always have to be code. People can contribute by creating issues or by fixing a broken link in the documentation. A lot of small improvements can still have a big impact for other community members. But if you don’t start to play in the hobby league you will probably not find them. 

Try All Features of Camunda

Related Content

Transition from simple deployments to a fully integrated production setup smoothly.
We're excited to announce the November 2024 alpha release of Camunda. Check out what's new.
We want to extend a huge welcome to our latest cohort of Camunda Champions. Learn about the latest group of leaders and what being a Champion means to them.