DEV Community

André Maré
André Maré

Posted on • Originally published at javanibble.com on

Implement a BPMN Service Task in Camunda

The article contains a step-by-step guide on how to implement a BPMN Service Task in Camunda making use of a Spring Boot Application. A Service Task within Camunda is used to either invoke Java code or to place a work item within a topic for an external worker to retrieve asynchronously.

What is a Service Task

“A Service Task is a Task that uses some sort of service, which could be a Web service or an automated application. A Service Task object shares the same shape as the Task, which is a rectangle that has rounded corners. However, there is a graphical marker in the upper left corner of the shape that indicates that the Task is a Service Task” ~ BPMN Specification

Getting Started Guide

The following is a step-by-step guide on how to implement a BPMN Service Task in Camunda making use of a Spring Boot Application.

Step 1: Create a Spring Boot Application

Create a spring boot application containing the Camunda BPM Engine. Use the Camunda BPM Initializr website to assist you in generating a Spring Boot application. Open the following URL in a browser and complete the form to bootstrap your application.

For a more detailed approach on how to create a spring boot application containing the Camunda BPM Engine, use the following link:

Step 2: Model the Process

Use Camunda Modeller to model the process. The process model is composed of four service tasks:

BPMN Service TaskExample of a service task

  • Retrieve Coffee Order: Is a Service Task using Java Class as implementation and com.javanibble.camunda.examples.RetrieveCoffeeOrderDelegate as the Java Class.
  • Make Coffee: Is a Service Task using Delegate Expressions as implementation and value of ${makeCoffee}.
  • Pour Coffee in Cup: Is a Service Task using Expression as implementation and value of ${coffeeService.pourCoffee(execution)}.
  • Deliver Coffee Order: Is a Service Task using External as implementation and topic value of deliverCoffeeOrder.

Camunda provides two ways for a service task to invoke services, namely Invoking Java Code and External Tasks. The above business process shows how to invoke services making use of several ways. The process engine invokes the java code synchronously except for the external tasks, where the process engine creates a work item and places it within a topic. External workers poll the process engine based on a topic and retrieve the work items.

Step 3 Invoke Java Code: Java Class

The “Retrieve Coffee Order” service task specifies a java class that implements a JavaDelegate. The Java class will be called during the process execution and hence the fully qualified name is required.

<bpmn:serviceTask id="retrieve-coffee-order" name="Retrieve Coffee Order" 
                  camunda:class="com.javanibble.camunda.examples.RetrieveCoffeeOrderDelegate">

Enter fullscreen mode Exit fullscreen mode

Create a Java class RetrieveCoffeeOrderDelegate that implements the org.camunda.bpm.engine.delegate.JavaDelegate interface.

package com.javanibble.camunda.examples;

public class RetrieveCoffeeOrderDelegate implements JavaDelegate {

    private final Logger LOGGER = LoggerFactory.getLogger(RetrieveCoffeeOrderDelegate.class.getName());

    public void execute(DelegateExecution execution) throws Exception {
        String coffeeOrder = (String) execution.getVariable("order");

        LOGGER.info("Order Coffee Process: " + execution.getCurrentActivityName() + " - " + coffeeOrder);
    }

}

Enter fullscreen mode Exit fullscreen mode

Step 4: Invoke Java Code: Delegate Expression

The “Make Coffee” service task makes use of a Delegate Expression that resolves to a specific object. This object must follow the same rules as objects that are created when the camunda:class attribute is used.

<bpmn:serviceTask id="make-coffee" name="Make Coffee" 
                  camunda:delegateExpression="${makeCoffee}">

Enter fullscreen mode Exit fullscreen mode

Create a Java class MakeCoffeeDelegate that implements the org.camunda.bpm.engine.delegate.JavaDelegate interface.

@Component("makeCoffee")
public class MakeCoffeeDelegate implements JavaDelegate {

    private final Logger LOGGER = LoggerFactory.getLogger(RetrieveCoffeeOrderDelegate.class.getName());

    public void execute(DelegateExecution execution) throws Exception {
        String coffeeOrder = (String) execution.getVariable("order");

        LOGGER.info("Order Coffee Process: " + execution.getCurrentActivityName() + " - " + coffeeOrder);
    }
}

Enter fullscreen mode Exit fullscreen mode

Step 5: Invoke Java Code: Expression

The “Pour Coffee in Cup” service task makes use of an expression which calls a method.

<bpmn:serviceTask id="pour-coffee-in-cup" name="Pour Coffee in Cup" 
                  camunda:expression="${coffeeService.pourCoffee(execution)}">

Enter fullscreen mode Exit fullscreen mode

Create a Java class CoffeeService and a method called pourCoffee that uses a DelegateExecution as a parameter.

@Component
public class CoffeeService {

    private final Logger LOGGER = LoggerFactory.getLogger(RetrieveCoffeeOrderDelegate.class.getName());

    public void pourCoffee(DelegateExecution execution) throws Exception {
        String coffeeOrder = (String) execution.getVariable("order");

        LOGGER.info("Order Coffee Process: " + execution.getCurrentActivityName() + " - " + coffeeOrder);
    }
}

Enter fullscreen mode Exit fullscreen mode

Step 6: External Task

The “Deliver Coffee Order” service task is handled externally as an external task. The camunda:type attribute is set toexternal and the camunda:topic attribute specifies the external tasks’ topic.

<bpmn:serviceTask id="deliver-coffee-order" name="Deliver Coffee Order" 
                  camunda:type="external" camunda:topic="deliverCoffeeOrder">

Enter fullscreen mode Exit fullscreen mode

There are several ways for external tasks to be implemented, but this example will use the REST APIs to fectAndLock and complete the external tasks.

Fetch & Lock External Task Fetches and locks a specific number of external tasks for execution by a worker. Query can be restricted to specific task topics and for each task topic an individual lock time can be provided.

curl --location --fail --silent --request POST 'http://localhost:8080/engine-rest/external-task/fetchAndLock' --header 'Content-Type: application/json' --data-raw '{"workerId":"aWorkerId","maxTasks":1,"usePriority":true,"topics":[{"topicName": "deliverCoffeeOrder","lockDuration": 10000,"variables": ["orderId"]}]}'

Enter fullscreen mode Exit fullscreen mode

Complete External Task Completes an external task by id and updates process variables.

curl --location --fail --silent --request POST "http://localhost:8080/engine-rest/external-task/$TASK_ID/complete" --header 'Content-Type: application/json' --data-raw '{"workerId": "aWorkerId","variables":{},"localVariables":{}}'

Enter fullscreen mode Exit fullscreen mode

Step 7: Create the Spring Boot Application class

The Spring Boot application is implemented by a class called BasicServiceTaskApplication. The class contains the @SpringBootApplication annotation that enables the spring boot auto configuration mechanism, enables the component scan on the packages and allow to register extra beans in the context.

@SpringBootApplication
public class BasicServiceTaskApplication {

    public static void main(String[] args) {
        SpringApplication.run(BasicServiceTaskApplication.class);
    }

}

Enter fullscreen mode Exit fullscreen mode

Step 8: Configure the Camunda Spring Boot Application

The properties and configuration of the Spring Boot Application can be found in the application.yaml file within the src/main/resources folder. To startup your Camunda BPM Spring Boot application, you need to set some properties to allows you access.

The properties to configure your admin-user are listed below:

camunda.bpm.admin-user:
  id: demo
  password: demo

spring.h2.console:
  enabled: true
  path: /h2-console

Enter fullscreen mode Exit fullscreen mode

Compile and Run the Application

To see the source code for the application and the set of commands to run the example, please see the rest of the article on my personal blog.

Implement a BPMN Service Task in Camunda

Finally

Congratulations !!! You have successfully implemented a BPMN Service Task in Camunda making use of a Spring Boot Application.

Discussion (0)