Activiti tutorial

[Updated to the version 7 of Activiti BPMN]

Activiti is an open-source BPMN platform distributed under the Apache license. It’s written in Java and thus can run in any Java application, on a server, on a cluster or in the cloud. Two deployment options are available for Activiti:

  • Activiti Cloud: which is a set of Cloud Native components designed from the ground up to work in distributed environments based on Kubernetes as main deployment infrastructure and Spring Cloud / Spring Boot along with Docker for containerization of these components.
  • Activiti Core: which is a set of API designed to run the BPMN 2.0 plarform in a Java standalone application / Spring Boot.

In this tutorial we will learn how to design a simple BPMN 2.0 process and use Activiti Core to run it in a Java application.

Installing the Activiti Process Designer

In order to design the BPMB 2.0 processes we will install the Activiti Eclipse plugin so that we can design our process from a Development IDE.

From the Eclipse upper menu, select Help | Install New Software. Choose to add the following Repository:

Next, check Activiti BPMN Designer as displayed by the following picture:

Click on Next and Finish the installation. You will need restarting Eclipse at the end of it.

Create a simple Standalone Project

Ok. Now let’s create a standalone application which uses Activiti API to start process instances and generates a Task list. To include the Activiti JAR and its dependent libraries, we advise using Maven as it simplifies dependency management on both our and your side a lot. Hence create a new Maven project at first:

$ mvn archetype:generate -DgroupId=com.mastertheboss.activiti -DartifactId=activitiDemo -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

Now we will need to include Activiti core libraries and some dependencies in the pom.xml file. Here is the list of dependencies we will add:


Done with the setup, we will now create a simple Process using the BPMN Designer.

Create a Process Diagram

Now Add an Activiti Diagram to your process from the menu File | New | Other | Activiti | Activiti Diagram.

Create a sample process in the resources folder of your Project. In our case, we will name the process MyProcess and we will save it in resources/DemoProcess.bpmn.
By clicking on it, the visual editor of Eclipse will appear. We will create a simple process definition which contains a ServiceTask, an Exclusive Gateway and two User Tasks. Here’s a picture of our process:

Now you need to configure each node. Select the Properties tab. We will configure first  the ServiceTask which simply recalls a callback method of a Java class implementing the JavaDelegate interface.

The Class we will simulate the choice between a Simple Task and a Complex Task which should be assigned to different actors:

package com.mastertheboss.task;

import org.activiti.engine.delegate.DelegateExecution;

public class JavaService1 implements org.activiti.engine.delegate.JavaDelegate {

	public void execute(DelegateExecution arg0) {

		if (isComplexTask()) {
			System.out.println("This is a complex task!");
			arg0.setVariable("result", "1");
		else  {
			System.out.println("This is a simple task!");			
		    arg0.setVariable("result", "0");


	private boolean isComplexTask() {
		return Math.random() < 0.5;


As you can see, this project contains two Tasks: we will assign each of them to a different Actor. Say, we will assign the first one to kermit and the second one to gonzo. Here’s the Properties for the first Task:

And, in turn for the second Task:

Finally we will configure the exclusiveGateway which can be seen as a Decision node. Depending on the value of “result” it will lead the process definition to two different Tasks. On each sequence flow choose a condition Expression: for example in upper Flow we will set the following condition:

Conversely, the lower Flow will capture the condition where result = 0:

Great, you are done with building your first Activiti Process.

Write a simple Activiti Client

Ok. Now the process is completed. We will add a minimal API to start the Process and claim the Tasks generated. 

package com.mastertheboss.activiti.main;

import org.activiti.engine.*;
import org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;

import java.util.List;
import java.util.Map;
import java.util.HashMap;

public class App
    public static void main( String[] args ) throws Exception

        ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
        ProcessEngine processEngine = cfg.buildProcessEngine();
        String pName = processEngine.getName();
        String ver = ProcessEngine.VERSION;
        System.out.println("ProcessEngine [" + pName + "] Version: [" + ver + "]");

        RepositoryService repositoryService = processEngine.getRepositoryService();
        Deployment deployment = repositoryService.createDeployment()
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                "Found process definition ["
                        + processDefinition.getName() + "] with id ["
                        + processDefinition.getId() + "]");

        final Map<String, Object> variables = new HashMap<String, Object>();
        final RuntimeService runtimeService = processEngine.getRuntimeService();

        ProcessInstance id = runtimeService.startProcessInstanceByKey("myProcess", variables);
        System.out.println("Started Process Id: "+id.getId());

        try {
            final TaskService taskService = processEngine.getTaskService();
            final List tasksSenior = taskService.createTaskQuery().taskAssignee("kermit").list();
            final List tasksJunior = taskService.createTaskQuery().taskAssignee("gonzo").list();

            if (tasksSenior.size() > 0) {
                System.out.println("Found task for Senior " +tasksSenior.get(0).getName() );
                taskService.claim(tasksSenior.get(0).getId(), "kermit");

                System.out.println("Task " +tasksSenior.get(0).getName() +" terminated");
            else if (tasksJunior.size() > 0) {
                System.out.println("Found task for Junior " +tasksJunior.get(0).getName() );
                taskService.claim(tasksJunior.get(0).getId(), "gonzo");

                System.out.println("Task " +tasksJunior.get(0).getName() +" terminated");

        } catch (Exception e) {
        } finally {



As you can see, the central starting point is the ProcessEngine. From the ProcessEngine, you can obtain the various services that contain the workflow/BPM methods.

Typically, there will be only one ProcessEngine instance needed in a end-user application. Building a ProcessEngine is done through a ProcessEngineBuilder instance and is a costly operation which should be avoided. For that purpose, it is advised to store it in a static field or JNDI location (or something similar).

Once started the class, an instance of the ProcessInstance will be created. The TaskService API is then used to retrieve the list of Tasks which can be claimed by the users “kermit” and “gonzo”. Depending on the Random number generated, the Task can be claimed by one of the two users, therefore a typical output of the execution would look like this:

This is a simple task!
Started Process Id: 5
Found task for Junior SimpleTask
Task SimpleTask terminated

You can download the source code for this article at: