How to start Activiti + Spring JPA with Spring Boot

In previous post, you was introduced BPMN and Activiti along with its API. This tutorial shows you a simple Spring Boot example which is integrated with Activiti and Spring JPA.

Related Articles:
Introduction to Activiti – a Java BPM Engine
Activiti Parallel Tasks + JPA with Spring Boot Example
Activiti REST API with Spring Boot Example
Reactjs Jwt SpringBoot Token Authentication Example
Angular Client Side Pagination with Nodejs + MySQL
Crud Operation in React.js and MySQL

I. Technology

– Java 1.8
– Maven 3.3.9
– Spring Tool Suite – Version 3.8.1.RELEASE
– Spring Boot: 1.5.3.RELEASE

II. Overview
1. Goal

To build a Spring Boot application that helps to manage process as below:
activiti-jpa-springboot-process

– We will create a group of persons and use Spring JPA to store their information.
– Then we assign Task 1 and Task 2 to one of them who is called assignee.
– After he finishes 2 tasks, ‘final Notice’ message will be shown in the System Console.

2. Project Structure

activiti-jpa-springboot

– Process definition will be written under XML format in process/simple-process.bpmn20.xml file.
MyService provides service methods for Controller such as: startProcess(), getTasks(), completeTask(). Those functions can be done with help of some @Autowired objects which are instances of these classes:
+ RepositoryService
+ RuntimeService
+ TaskService
+ PersonRepository
PersonRepository is an interface extends JpaRepository for implementing repository methods on Person entities.

SpringStarterActivitiApplication class contains Bean that calls MyService‘s creating persons method when starting the application.
MyController is a REST Controller which has request mapping methods for RESTful requests such as: /process, /tasks, /completetask.

pom.xml contains dependencies for:
+ Activiti Spring Boot Starter Basic, Activiti Spring Boot Starter JPA
+ Spring Boot Starter Web
+ H2 database
+ Groovy: scripting engine for running Script Task in process.

Notes: We must add Groovy Jar file (groovy-all-2.4.10.jar) to make it work.
3. Step to do

We will follow these steps to make things done:
– Create Spring Boot project
– Define Process
– Create DataModel Class and JPA Repository Interface
– Create Service Class
– Create Application Class
– Create Controller
– Run & Check Result

III. Practice
1. Create Spring Maven project

– Using Spring Tool Suite to create Project and add Dependencies to pom.xml file:

		
			org.codehaus.groovy
			groovy-all
		

		
			com.h2database
			h2
		

		
			org.activiti
			activiti-spring-boot-starter-basic
			5.22.0
		

		
			org.activiti
			activiti-spring-boot-starter-jpa
			5.22.0
		

		
			org.springframework.boot
			spring-boot-starter-web
		

– Add Groovy Jar file (groovy-all-2.4.10.jar) as Referenced Library.

2. Define Process

Under src/main/resources, create processes folder and add simple-process.bpmn20.xml file:




	
		
		

		
			
				Do the first task.
			
		

		

		
			
				Work for the second task.
			
		

		

		%MINIFYHTML00d860b05ad0af6c5cf1f6e7a460855118%

		
		
	


We use ${person.name} expression and activiti:assignee attribute for assigning task.

3. Create DataModel Class and JPA Repository Interface
package com.javasampleapproach.activiti.model;

import java.util.Date;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Person {
	@Id
	@GeneratedValue
	private Long id;

	private String name;

	private Date birthDate;

	public Person() {
	}

	public Person(String name, Date birthDate) {
		this.name = name;
		this.birthDate = birthDate;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

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

	public Date getBirthDate() {
		return birthDate;
	}

	public void setBirthDate(Date birthDate) {
		this.birthDate = birthDate;
	}

}
package com.javasampleapproach.activiti.repo;

import org.springframework.data.jpa.repository.JpaRepository;

import com.javasampleapproach.activiti.model.Person;

public interface PersonRepository extends JpaRepository {

	Person findByName(String name);

}
4. Create Service Class
package com.javasampleapproach.activiti.service;

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

import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.javasampleapproach.activiti.model.Person;
import com.javasampleapproach.activiti.repo.PersonRepository;

@Service
@Transactional
public class MyService {

	@Autowired
	private RepositoryService repositoryService;

	@Autowired
	private RuntimeService runtimeService;

	@Autowired
	private TaskService taskService;

	@Autowired
	private PersonRepository personRepository;

	public String startProcess(String assignee) {
		Person person = personRepository.findByName(assignee);

		Map variables = new HashMap();
		variables.put("person", person);

		runtimeService.startProcessInstanceByKey("simpleProcess", variables);

		return processInfo();
	}

	public List getTasks(String assignee) {
		return taskService.createTaskQuery().taskAssignee(assignee).list();
	}
	
	public void completeTask(String taskId) {
		taskService.complete(taskId);
	}

	public void createPersons() {
		if (personRepository.findAll().size() == 0) {

			personRepository.save(new Person("John", new Date()));
			personRepository.save(new Person("David", new Date()));
			personRepository.save(new Person("Katherin", new Date()));
		}
	}

	private String processInfo() {
		List tasks = taskService.createTaskQuery().orderByTaskCreateTime().asc().list();
		
		StringBuilder stringBuilder = new StringBuilder();

		stringBuilder.append("Number of process definitions : "
				+ repositoryService.createProcessDefinitionQuery().count() + "--> Tasks >> ");

		for (Task task : tasks) {
			stringBuilder
					.append(task + " | Assignee: " + task.getAssignee() + " | Description: " + task.getDescription());
		}

		return stringBuilder.toString();
	}
}
5. Create Application Class
package com.javasampleapproach.activiti;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

import com.javasampleapproach.activiti.service.MyService;

@SpringBootApplication
public class SpringStarterActivitiApplication {

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

	@Bean
	public CommandLineRunner init(final MyService myService) {

		return new CommandLineRunner() {
			public void run(String... strings) throws Exception {
				myService.createPersons();
			}
		};

	}

}
6. Create Controller
package com.javasampleapproach.activiti.controller;

import java.util.List;

import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.javasampleapproach.activiti.service.MyService;


@RestController
public class MyController {

	@Autowired
	private MyService myService;

	@RequestMapping(value = "/process")
	public String startProcessInstance(@RequestParam String assignee) {
		return myService.startProcess(assignee);
	}

	@RequestMapping(value = "/tasks/{assignee}")
	public String getTasks(@PathVariable("assignee") String assignee) {
		List tasks = myService.getTasks(assignee);
		return tasks.toString();
	}

	@RequestMapping(value = "/completetask")
	public String completeTask(@RequestParam String id) {
		myService.completeTask(id);
		return "Task with id " + id + " has been completed!";
	}

}
7. Run & Check Result

– Config maven build:
clean install
– Run project with mode Spring Boot App
– Check results by open your browser and send request:

Request 1: Assign tasks to David
http://localhost:8080/process?assignee=David

Number of process definitions : 1--> Tasks >> Task[id=8, name=Task 1] | Assignee: David | Description: Do the first task.

Request 2: show tasks of David
http://localhost:8080/tasks/David

[Task[id=8, name=Task 1]]

David has only one Task at the present because he hasn’t done the Task 1.

Request 3: complete Task 1
http://localhost:8080/completetask?id=8

Task with id 8 has been completed!

Request 4: show tasks of David
http://localhost:8080/tasks/David

[Task[id=11, name=Task 2]]

David now works on Task 2.

Request 5: complete Task 2
http://localhost:8080/completetask?id=11

Task with id 11 has been completed!

And System Console shows:

finish Process.

IV. Source Code

SpringStarterActiviti



By grokonez | May 13, 2017.

Last updated on February 4, 2021.



Related Posts


11 thoughts on “How to start Activiti + Spring JPA with Spring Boot”

  1. Greetings,
    I tried to run this application but i get this following error :
    Description:

    Parameter 1 of method springProcessEngineConfiguration in org.activiti.spring.boot.JpaProcessEngineAutoConfiguration$JpaConfiguration required a bean of type ‘javax.persistence.EntityManagerFactory’ that could not be found.

    Action:

    Consider defining a bean of type ‘javax.persistence.EntityManagerFactory’ in your configuration.

    what should i do.

    thanks

    1. Hi Manish,

      Just change configuration in application.properties file for MySQL database 🙂

      Regards,
      JSA.

  2. Hello, your tests fail =/ with the following error
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘entityManagerFactory’

  3. Hi nice.. I have 2 tables Emp and Role having some values in backend(Postgres).
    I want to create a simple flow ->
    Task 1 – Invoke process by fetching Employee IDs from Emp (1 / 2 / 3 /etc)..
    Task 2 – It will check in DB if user exists, if true proceed ahead else terminate.
    Task 3 – If user exists, then, check its dept.
    If dept -> IT – Task 4 to execute.
    If dept -> Finance – Task 5 to execute.
    If dept -> Not Assigned – Task 6 to execute.

    How to achieve this? I have already created some methods in ServiceLayer of SpringBoot, which I need to execute for every Task defined above. How to achieve this?

  4. Thank you so much for taking time out to produce this.
    This is the best, and yet simplified, introduction to embedding Activiti BPM into Java applications!
    Again, thank you for putting this together.
    You just made my work very easy and saved me countless trials!

  5. hi,
    it shows an error “The archive: E:/STS/groovy-all-2.4.10.jar which is referenced by the classpath, does not exist.”

    please help !

    Regards,
    Ankur

  6. how can i add this to spring mvc instead of spring boot? is it possible to create activiti framework with maven spring mvc project?

Got Something To Say:

Your email address will not be published. Required fields are marked *

*