Using Camunda for easy orchestration based on REST and Workflow Engine (no Java)

Hey Habr! I present to your attention 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/XNUMX/XNUMX, translation Articles Bernd Rucker

Using Camunda for easy orchestration based on REST and Workflow Engine (no Java)

I often discuss microservice architecture with non-Java people: C# developers, Node.JS/JavaScript developers, or Golang aficionados. All of them are faced with the fact that they need an orchestration mechanism in a microservice architecture, or just a tool to streamline the workflow and gain the ability to order, handle timeouts, Saga and compensating transactions.

BPM platform with open source from Camunda great for such tasks. Developer friendliness 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 a lot of options for connecting your own functions and extensions, but it's all done in Java. Is it really?

No! In fact, you can easily run Camunda without any Java knowledge and set up the architecture for code in any language of your choice. In this article, we will look at:

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

Architecture

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 easy orchestration based on REST and Workflow Engine (no Java)

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

Running Camunda through a pre-built Docker image

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

Using Camunda for easy orchestration based on REST and Workflow Engine (no Java)

In this case, simply run:

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

You don't have to worry about Linux, JVMs or Tomcats. Dockerfiles and basic documentation (for example, instructions for connecting to the required databases) are available at Github.

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

However, running Camunda with Docker has one downside: you'll end up with a version of Tomcat that doesn't always include the latest fixes. To work around this, you can create your own Docker image based on the desired Tomcat distribution, as shown in this example, or use one of the solutions described below.

Process Model Deployment

Let's look at an example using the Saga template for a classic trip booking where you want to trigger three actions in a row and gracefully compensate for successfully completed actions in case of a later failure. Represented in BPMN form, it looks like this:

Using Camunda for easy orchestration based on REST and Workflow Engine (no Java)

Now you can use REST API for process model deployment. Let's say you save it as trip.bpmn and run Camunda via Docker so it's 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 "[email protected]" 
http://localhost:8080/engine-rest/deployment/creat

Now you can run new workflow instances using the REST API and pass the data 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 Camunda call procedures like booking a car? Camunda can not only call services immediately (Push-Principle) using some built-in connectors, but also put work items in a kind of built-in order. The worker can then fetch work items via REST, perform the work, and tell Camunda to complete (Pull-Principle).

Using Camunda for easy orchestration based on REST and Workflow Engine (no Java)

So first you need to execute fetchAndLock (because other workers can 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 completed work (note that you must enter the external task id received 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 a REST API is easy in any programming language. In JavaScript, this is conveniently done using JQuery, and in C#, using System.Net.Http and Newtonsoft.Json. But this will take time. So you can just use some client library.

At the moment, several ready-made client libraries are available:

  • JavaScript: link. Supported by Camunda;
  • Java: link. Supported by Camunda;
  • C #: link и link. Both of these projects are in an intermediate state and practically dormant, but can serve as a good starting point;
  • PHP: link - not too complete and does not include the latest API changes, but I know projects that use it.

With the exception of JavaScript and Java, the client libraries are not part of the Camunda product itself. Don't expect them to support all of Camunda's REST API features. Just because a library doesn't provide a certain function doesn't mean it's not there, always check Camunda's REST API. Reference 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 online: 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 the website github.com

Alternative Ways to Launch Camunda

Custom Docker image with "Camunda standalone WAR"

As an alternative to a pre-built Docker image from Camunda, 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 easy orchestration based on REST and Workflow Engine (no Java)

If you have many additional requirements and can set up a Java build environment, you can also set up Camunda Standalone war. Set up a Maven build like in these examples: build Maven with war config or assembly Maven with Overlay.

Starting the Camunda Tomcat distribution

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

Using Camunda for easy orchestration based on REST and Workflow Engine (no Java)

In order to change the database or do anything else you need to configure Tomcat like described in documentation. I know Tomcat may sound complicated, but it's actually 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 set up Tomcat yourself and install Camunda into it, following the installation description. This will give you the option to use whichever version of Tomcat you prefer, or install it as a Windows service, for example.

Launching Camunda into production

This will usually require some final setup to run Camunda. There are guidelines in Camunda that describe this in great detail, but I will not go into them in this article - I will name just one example: the distribution's REST API is not configured for authentication by default. You may want to change this.

Summing-up

As you can see, it's very easy to get started with Camunda, regardless of the language you're using. The key point is that all interaction is done through the REST API. Installation is pretty easy too, especially when using Docker.

Source: habr.com

Add a comment