Creating a Workflow with Spring Boot and Camunda

Dilara ÜNBAY
Orion Innovation techClub
8 min readJan 10, 2024

In this article, we will develop a simple Spring Boot application in which we embed the Camunda Engine. By the end of this article, we will learn how to call Spring Boot services via Camunda and fill in their parameters.

Prerequisites:

  • IntelliJ IDEA
  • Maven
  • Java 8
  • Camunda Modeler

I’ve suggested IntelliJ IDEA since I will be using it throughout this article. Otherwise, you are free to use an IDE of your preference.

You can skip the step-by-step tutorial and directly import the code from the following link:

Github

Firstly, let’s create an empty Spring Boot project in Camunda Engine via Camunda Automation Platform 7 Initializr. After filling in the required fields, click on the “Generate Project” button.

Transfer the contents of the downloaded zip file to your desktop or any other file you see fit. Then, open the unzipped project in IntelliJ IDEA. Your project structure should be similar to this:

After checking your project structure, open the “pom.xml” file. Add “camunda-connect-core” and “camunda-engine-plugin-connect” requirements inside the “dependencies” tag, which has other camunda dependencies listed. We will use “Connector” to fill in the service parameters later in the article. With the help of these requirements, Camunda Engine will be able to successfully parse our bpmn file containing the “Connector”.

    <dependency>
<groupId>org.camunda.connect</groupId>
<artifactId>camunda-connect-core</artifactId>
</dependency>

<dependency>
<groupId>org.camunda.bpm</groupId>
<artifactId>camunda-engine-plugin-connect</artifactId>
</dependency>

Since we are using Java 8, we need to update the Spring Boot and Camunda versions imported in the “pom.xml”. If you want to use the latest versions of both, you need to use Java 17.

  <dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.6.4</version>
<type>pom</type>
<scope>import</scope>
</dependency>

<dependency>
<groupId>org.camunda.bpm</groupId>
<artifactId>camunda-bom</artifactId>
<version>7.15.0</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>

Once you have completed the requirements, check your “application.yaml” file. You can update your login credentials by altering “id” and “password” fields. Also, you can set a username which will appear in the interface by adding “first-name” and “last-name” variables.

spring.datasource.url: jdbc:h2:file:./camunda-h2-database

camunda.bpm.admin-user:
id: camundademo
password: camundademo
first-name: Camunda
last-name: Demo

Before we start coding, let’s briefly talk about the workflow diagram we have in mind. In the first step, we will request two inputs from the user, which are name and message. In the second step, we will pass these inputs to our service to create a message output. To create this workflow, we first need an object consisting of a name and a message.

To code our object, let’s open a class named “model” under “com.example.workflow”. Within the class, define two String type variables “name” and “message” respectively. Then, create Getter and Setter methods for the variables. Finally, define an empty Constructor and create a simple toString method to properly display our object.

public class model {

private String message;
private String name;

public model() { }

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return "" + message + ", " + name;
}
}

Before moving on to the workflow, let’s code the service which will be responsible for our message output. Open a class named “controller” under “com.example.workflow”. Specify the extension of the service and the data it will receive by adding Spring annotations. Then, create a new model named “m” and save the model data received by the service. Finally, add a logger in the class to make sure that the service is running and receiving the data sent from Camunda.

@RequestMapping("/")
@RestController
public class controller {
java.util.logging.Logger logger =
java.util.logging.Logger.getLogger(this.getClass().getName());

@PostMapping("/message")
public model createMessage(@RequestBody model model) {
logger.info("-------Message Creator Initialized-------");

model m = new model();
m.setMessage(model.getMessage());
m.setName(model.getName());

logger.info("Message created --> " + m.toString());
return m;
}
}

This concludes the Spring Boot side of our project. Now, we can start creating our workflow diagram. Open the “process.bpmn” which is under “resources” in our project in the Camunda Modeler Application. Make sure you open the bpmn file located in your project. In the opened bpmn file, you will see a “User Task” shown with a human icon.

User Tasks are the steps where user-related operations are carried out. As mentioned in the previous sections, in the first step of our workflow, we will request two inputs from the user: name and message. Instead of adding a new task, updating the existing “User Task” will do the trick.

Click on the “User Task” and then open the “Properties Panel”. Define an identity and a name suitable for our case in the opened panel.

After finishing the general information, move on to the “Forms” tab. This is the tab where, the form presented to the user is defined. Since we need name and message inputs from the user, let’s define two form fields named “name” and “message”. To define a form field, click on the plus icon next to the “Form Fields”. In the opened form, fill in the ID, type and label fields accordingly. Repeat the same steps for each form field.

This concludes the first step of our workflow. Let’s move on to the second step, where we call our service. To add a “Service Task”, click on the “Create Task” icon from the menu on the left and drop the task to a random location. After clicking on the task, click on the “Change Type” icon and select “Service Task” from the menu.

For the general information, repeat the previous steps. Additionally, select the “Connector” option from the “Implementation” menu.

After selecting an implementation, switch to the “Connector” tab. This is the tab where HTTP information and the data regarding the service is defined. Firstly, click on the plus icon next to the “Input Parameters” heading. Fill in the Name and Type fields as “headers” and “Map” respectively. From the “Add Entry” option that opens, add an entry with the key “Content-Type” and the value “application/json”. With these entries, we indicate that the data is in JSON format. Create and fill in the remaining input parameters like “payload”, “method” and “url” based on the screenshots given below:

By using the “${}” format in the payload, the “message” and “name” inputs received in the previous step will be passed on to the service.

Writing “POST” in the method indicates that the service makes a HTTP POST request.

Finally, with the url parameter, we give the proper address to reach our service. Make sure that the port you enter the url matches the port your project is running on.

To connect the “Service Task” to the workflow, delete the existing arrow between the “User Task” and the “End Event”. Then, click on the “User Task” and select the arrow icons from the menu. Connect the arrow to the “Service Task”. Lastly, repeat the same steps for the “Service Task” and the “End Event”. Verify that your workflow looks similar to the one provided below and save your workflow diagram. You will see that the code inside the “process.bpmn” file will be updated on the IntelliJ IDEA.

With the completion of the workflow, we are ready to run the project in the debug mode. After you run the project and see a text similar to “Started Application in 8.096 seconds” in the console, go to the address http://localhost:8080/ on your browser. When you access the page, you will see the Camunda login page. Enter the login credentials you provided in “application.yaml” to log in successfully.

Select “Tasklist” from the main page of applications and on the tasklist page click on the “Add a simple filter” option. After clicking, you will see that a filter named “All Tasks (0)” has been added to the list. Then, click on the “Start process” option to run the workflow we have prepared.

Select the process named “camunda-spring-demo-process” and click on the “Start button” without providing any additional information. Finally, click on the “Get Input” task listed under “Created”. If you don’t see the task, refresh the page.

You will see the form we defined in the first step. To fill out the form, click on the “Claim” option at the top right corner. Then, fill out the form to your liking and click the “Complete” button.

As the workflow executes the “Service Task” and the service runs, you’ll see that the list becomes empty again. If the workflow successfully executed the second step, we should be able to see the output in our console, which we printed with the help of a Logger. The output should include the inputs you, as the user, provided.

Congratulations on finishing the tutorial and thank you for reading through my post. If you faced any problem following this tutorial, you can reach out to me in the comments section.

--

--