Hello, Habr! I present to you the translation of the article " Use Camunda as an easy-to-use REST-based orchestration and workflow engine (without touching Java) " by Bernd Rücker.

07.07.2020, translation articles Bernd Rücker

Using Camunda for convenient orchestration

I often discuss microservice architecture with people far from Java: C # developers, Node.JS/JavaScript, or Golang adherents. All of them are faced with the fact that they need an orchestration mechanism in microservice architecture or just a tool to optimize the workflow and get the ability to streamline, process timeouts, Saga and compensating transactions.


BPM platform with Camunda's open source is great for such tasks. Friendliness towards the developer is one of the key features of the product. But if you look at its documentation, you might get the impression that Camunda’s “friendliness” is mainly aimed at Java developers. The platform provides many possibilities for connecting its own functions and extensions, but all this is done in Java. Is this really so?

No! In fact, you can easily launch Camunda without any Java knowledge and configure the architecture for code in any language of your choice. In this article we will consider:

  • basic architecture;
  • Tips on existing client libraries for languages ​​other than Java;
  • C # and Node.JS example;
  • ways to start the Camunda server (Docker or Tomcat).


Camunda is written in Java and needs a Java Virtual Machine (JVM) to run. Camunda provides a REST API that allows you to write in any language you like and use REST with Camunda:

Using Camunda for conveniently orchestrating

Workflows in Camunda are defined in BPMN, which is basically an XML file. It can be modeled using Camunda Modeler .

Launching Camunda through a pre-built Docker image

The easiest way to start Camunda is to use Docker. Alternative ways to launch Camunda are described later in this article.

Using Camunda for convenient orchestration

In this case, just run:

docker run -d -p 8080:8080 camunda/camunda-bpm-platform:latest 

You don’t need to worry about Linux, Java virtual machines or Tomcats. Dockerfiles and basic documentation (for example, instructions on connecting to the required databases) are available on Github .

If you want to run Camunda Enterprise Edition, you can easily change Dockerfile .

However, running Camunda using Docker has one drawback: you get a version of Tomcat that does not always include the latest fixes. To get around this somehow, you can create a Docker image yourself based on the desired Tomcat distribution, as shown in this example, or use one of the solutions described below.

Deploying a process model

Let's look at an example using the Saga template for classic travel bookings, where you want to call up three actions in a row and correctly compensate for successful actions in case of a later failure.Presented in BPMN form, it looks like this:

Using Camunda for convenient orchestration

Now you can use the REST API to deploy the process model . Suppose you save it with the name trip.bpmn and run Camunda through Docker so that it is available on localhost: 8080:

curl -w "\n" \ -H "Accept: application/json" \ -F "deployment-name=trip" \ -F "enable-duplicate-filtering=true" \ -F "deploy-changed-only=true" \ -F "trip.bpmn=@trip.bpmn" \ http://localhost:8080/engine-rest/deployment/creat 

Now you can run new workflow instances using the REST API and transfer the data that you want to see as workflow instance variables:

curl \ -H "Content-Type: application/json" \ -X POST \ -d '{"variables":{"someData" : {"value" : "someValue", "type": "String"}},"businessKey" : "12345"}}' \ http://localhost:8080/engine-rest/<!-- -->process-definition/key/<!-- -->FlowingTripBookingSaga<!-- -->/start 

The next interesting question is: how does the Camunda call procedures like booking a car? Camunda can not only immediately call services (Push-Principle), using some of the built-in connectors , but also put work items in a kind of built-in order. After that, the worker can receive work items via REST, do the work, and inform Camunda of completion (Pull-Principle).

Using Camunda for convenient orchestration

So first you need to do fetchAndLock (as other workers may receive tasks at the same time to scale the system):

curl \ -H "Content-Type: application/json" \ -X POST \ -d <!-- -->'{"workerId":"worker123","maxTasks":1,"usePriority":true,"topics":[{"topicName": "reserve-car"}, "lockDuration": 10000, "variables": ["someData"]}]}'<!-- --> \ http://localhost:8080/engine-rest/external-task/fetchAndLock 

Then tell Camunda that worker has completed work (please note that you must enter the external task identifier obtained in the first request):

curl \ -H "Content-Type: application/json" \ -X POST \ -d <!-- -->'{"workerId":"worker123", "variables": {}}'<!-- --> \ http://localhost:8080/engine-rest/<!-- -->external-task/EXTERNAL_TASK_ID/complete 

That's it - you still haven't needed any Java, right? And that’s enough to get started!

Client Libraries

Calling the REST API is easy in any programming language. In JavaScript, this is conveniently done using jQuery, while in C #, you can use System.Net.Http and Newtonsoft.Json. But it will take time. So you can just use some client library.

Currently, several ready-made client libraries are available:

  • JavaScript: link . Camunda supported;
  • Java: link . Camunda supported;
  • C #: link and link . Both of these projects are in an intermediate state and are practically inactive, but can serve as a good starting point;
  • PHP: link - the library is not too full and does not include the latest API changes, but I know projects using it.

With the exception of JavaScript and Java, client libraries are not part of the Camunda product itself. Do not expect them to support all of Camunda's REST API features. If the library does not provide a specific function, this does not mean that it is not there, always check the Camunda REST API. Typical projects use libraries as a starting point and template.

C # example

Using the above client library, we can simply write:

var camunda=new CamundaEngineClient("http://localhost:8080/engine-rest/engine/default/", null, null);//Deploy the BPMN XML file from the resources camunda.RepositoryService.Deploy("trip-booking", new List<object> { FileParameter.FromManifestResource(Assembly.GetExecutingAssembly(), "FlowingTripBookingSaga.Models.FlowingTripBookingSaga.bpmn") });//Register workers registerWorker("reserve-car", externalTask => {//here you can do the real thing! Like a sysout :-) Console.WriteLine("Reserving car now..."); camunda.ExternalTaskService.Complete(workerId, externalTask.Id); }); registerWorker("cancel-car", externalTask => { Console.WriteLine("Cancelling car now..."); camunda.ExternalTaskService.Complete(workerId, externalTask.Id); }); registerWorker("book-hotel", externalTask => { Console.WriteLine("Reserving hotel now..."); camunda.ExternalTaskService.Complete(workerId, externalTask.Id); });//Register more workers... StartPolling(); string processInstanceId=camunda.BpmnWorkflowService.StartProcessInstance("FlowingTripBookingSaga", new Dictionary<string, object>() { {"someBookingData", "..." } }); 

The fully working source code can be found on the Internet: link . Another example is available at link .

Example with Node.js

var Workers=require('camunda-worker-node'); var workers=Workers('http://localhost:8080/engine-rest', { workerId: 'some-worker-id' }); workers.registerWorker('reserve-car', [ 'someData' ], function(context, callback) { var someNewData=context.variables.someData + " - added something"; callback(null, { variables: { someNewData: someNewData } }); }); workers.shutdown(); 

More information can be found on github.com

Alternative Camunda Launch Methods

Custom Docker Image with Camunda standalone WAR

As an alternative to Camunda’s finished Docker, you can prepare Tomcat yourself (for example, based on the official Docker Tomcat images), and then copy Camunda into it as one of the so-called WAR files.

Using Camunda for convenient orchestration

If you have many additional requirements and you can customize the Java build environment, you can also customize the Camunda Standalone war. Configure the Maven assembly as in these examples: the Maven assembly with war configuration or the assembly Maven with Overlay .

Launch Camunda Tomcat distribution

Another option is to simply download the Camunda Tomcat distribution, unzip it and run it. All you need is the Java Runtime Environment (JRE) installed on your computer. It can be easily download from here .

Using Camunda for convenient orchestration

To change the database or do something else, you need to configure Tomcat as described in the documentation . I know that Tomcat may seem complicated, but in fact it is very simple. And Google knows the answers to everything that may be required in the process.

Running Camunda using Tomcat

The last alternative is to configure Tomcat yourself and install Camunda in it, following the installation description . This will make it possible to use any version of Tomcat that you prefer, or, for example, install it as a Windows service.

Launching Camunda in production

Generally, for this you will need to make some final settings to launch Camunda. Camunda has recommendations that describe this in great detail, but I won’t touch on them in this article - I’ll just give you one example: The distribution's REST API is not configured for authentication by default. You might want to change this.


As you may have noticed, getting started with Camunda is very easy, regardless of the language you use. The key point is that all interaction is done through the REST API. Installation is also quite simple, especially when using Docker.