Spring Boot + Activiti Service Task Example
In this tutorial, we will discuss Spring Boot + Activiti Service Task example. Service task is used to invoke an external Java class. A service task is visualized as a rounded rectangle with a small gear icon in the top-left corner.
Activiti is an open-source workflow engine that can execute business processes described in BPMN 2.0 and in our previous example on Spring Boot + Activiti, we had discussed the basic fundamental of Activiti workflow engine and create a user task, assigned the task to a user and user will complete it.
BPMN 2.0 introduced many sub-tasks under task category like user task, service task, script task, camel task, etc for different purposes and workflow process engine execute them. On this page, we will execute the Service Task using Activiti workflow engine.
What we’ll build
Today, we are going to design a Service Task using the Activiti Designer plugin and execute them via Activiti workflow engine. Our service task will print some message on the console.
1. Technologies Used
Find the list of all technologies used in this application.
- STS 3
- JDK 8
- Spring Boot 1.5.3.RELEASE
- Activiti 5.22.0
- H2 Database
2. Dependencies Required
Add the following to your pom.xml.
<properties>
<java.version>1.8</java.version>
<activiti.version>5.22.0</activiti.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter-basic</artifactId>
<version>${activiti.version}</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
</dependencies>
3. Invoking Java Logic
There are 4 ways of declaring how to invoke Java logic in service task:
- Specifying a class that implements JavaDelegate or ActivityBehavior
- Evaluating an expression that resolves to a delegation object
- Invoking a method expression
- Evaluating a value expression
In our demonstration, we are going to use only Java Delegate (first) and Method Expression (third) to execute our Java logic in service task.
3.1.1 Class that implements JavaDelegate
Create a JavaDelegateService
class which implements JavaDelegate
interface of package org.activiti.engine.delegate
. Override it’s execute()
method and put your Java logic to be executed by service task.
package org.websparrow.activiti.service;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.JavaDelegate;
import org.springframework.stereotype.Service;
@Service
public class JavaDelegateService implements JavaDelegate {
@Override
public void execute(DelegateExecution execution) throws Exception {
System.out.println("Java Delegate Service Task executed successfully.");
System.out.println("And the Sum of 2 + 2= " + (2 + 2));
}
}
3.1.2 JavaDelegate BPMN Process Definition
Drop the BPMN 2.0 process definition into the src/main/resources/processes folder. To specify a class that is called during the process execution, the fully qualified class name needs to be provided by the activiti:
class attribute.
<serviceTask id="javadeletegateservicetask" name="Java Delegate Service Task"
activiti:class="org.websparrow.activiti.service.JavaDelegateService">
</serviceTask>
See the complete process definition.
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI"
typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath"
targetNamespace="Examples">
<process id="java-delegate-service-task-process" name="Activiti Service Task using Java Delegates"
isExecutable="true">
<startEvent id="startevent1" name="Start"></startEvent>
<serviceTask id="javadeletegateservicetask" name="Java Delegate Service Task"
activiti:class="org.websparrow.activiti.service.JavaDelegateService"></serviceTask>
<sequenceFlow id="flow1" sourceRef="startevent1"
targetRef="javadeletegateservicetask"></sequenceFlow>
<endEvent id="endevent1" name="End"></endEvent>
<sequenceFlow id="flow2" sourceRef="javadeletegateservicetask"
targetRef="endevent1"></sequenceFlow>
</process>
</definitions>
The above BPMN process definition gives you the below-visualized diagram:
3.1.3 JavaDelegate Controller
Create DelegateServiceTaskController
class which autowired the RuntimeService
and execute the process by its process instance key.
package org.websparrow.activiti.controller;
import org.activiti.engine.RuntimeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("activiti")
public class DelegateServiceTaskController {
@Autowired
private RuntimeService runtimeService;
@GetMapping("service/delegate")
public String startTheProcess() {
runtimeService.startProcessInstanceByKey("java-delegate-service-task-process");
return "Check the console log...";
}
}
Output: Now everything is all set, hit the http://localhost:8080/activiti/service/delegate URL in your web browser and check your IDE console log. You will get the:
Java Delegate Service Task executed successfully.
And the Sum of 2 + 2= 4
3.2.1 Invoking a method expression
Invoking the Java classes using method expression is another great way to execute your business logic in the workflow diagram. Create a MethodExpressionService
class where the business logic will be executed inside the myService()
method.
package org.websparrow.activiti.service;
import org.springframework.stereotype.Service;
@Service
public class MethodExpressionService {
public void myService() {
System.out.println("Method Expression Service Task executed successfully.");
System.out.println("And the Multiply of 2 * 2= " + (2 * 2));
}
}
3.2.2 Method Expression BPMN Process Definition
Drop the BPMN 2.0 process definition into the src/main/resources/processes folder. To specify a class method that is called during the process execution, method expression uses the Spring bean which is implemented with attribute activiti:
expression.
<serviceTask id="methodExpressionServiceTask" name="Method Expression Service Task"
activiti:expression="${methodExpressionService.myService()}">
</serviceTask>
See the complete process definition.
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI"
typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath"
targetNamespace="Examples">
<process id="method-expression-service-task-process" name="Activiti Service Task using Method Expression"
isExecutable="true">
<startEvent id="startevent1" name="Start"></startEvent>
<serviceTask id="methodExpressionServiceTask" name="Method Expression Service Task"
activiti:expression="${methodExpressionService.myService()}"></serviceTask>
<sequenceFlow id="flow1" sourceRef="startevent1"
targetRef="methodExpressionServiceTask"></sequenceFlow>
<endEvent id="endevent1" name="End"></endEvent>
<sequenceFlow id="flow2" sourceRef="methodExpressionServiceTask"
targetRef="endevent1"></sequenceFlow>
</process>
</definitions>
The above BPMN process definition gives you the below-visualized diagram:
3.2.3 Method Expression Controller
Create ExpressionServiceTaskController
class which autowired the RuntimeService
and execute the process by its process instance key.
package org.websparrow.activiti.controller;
import org.activiti.engine.RuntimeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("activiti")
public class ExpressionServiceTaskController {
@Autowired
private RuntimeService runtimeService;
@GetMapping("service/expression")
public String startTheProcess() {
runtimeService.startProcessInstanceByKey("method-expression-service-task-process");
return "Check the console log...";
}
}
Output: Hit the http://localhost:8080/activiti/service/expression URL in your web browser and check the console log. You will get the:
Method Expression Service Task executed successfully.
And the Multiply of 2 * 2= 4
4. Project Structure
Final project structure of our application in STS ide will look like as follows:
References
- Spring Boot + Activiti Example
- Java Service Task- Activiti User Guide
- Getting started with Activiti and Spring Boot
Download Source Code: spring-boot-activiti-service-task-example.zip