Simple Activiti BPM and Spring for task assignment

Hi all,

I am finally back to write some simple codes to enable for the other to learn, I hope with the simple code reader may get the concept within and enable to elaborate and adapt to their project. This is my first post in year 2013 after sometimes to took a break. In this article I would like to show you simple Activiti BPM that is combined with Spring to create simple java code (No Web application but Java Console only) for simple task assignment.

First thing first, What we need to do the environment such as database (MySQL) and coding editor (Eclipse)

1. Create your maven project in the eclipse

2. After all the folder project setup and it is time to manage the dependencies in the POM.xml

<repositories>
 <repository>
 <id>activiti</id>
 <name>Activiti Repository</name>
 <url>https://maven.alfresco.com/nexus/content/repositories/activiti/</url>
 </repository>
</repositories>
<dependencies>
 <dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 <version>3.8.1</version>
 <scope>test</scope>
 </dependency>
 <dependency>
 <groupId>org.activiti</groupId>
 <artifactId>activiti-engine</artifactId>
 <version>5.11</version>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-core</artifactId>
 <version>3.1.2.RELEASE</version>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-context</artifactId>
 <version>3.1.2.RELEASE</version>
 </dependency>
 <dependency>
 <groupId>org.activiti</groupId>
 <artifactId>activiti-spring</artifactId>
 <version>5.11</version>
 </dependency>
 <dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 <version>5.1.22</version>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-aspects</artifactId>
 <version>3.1.2.RELEASE</version>
 </dependency>
 <dependency>
 <groupId>org.aspectj</groupId>
 <artifactId>aspectjrt</artifactId>
 <version>1.7.0</version>
 </dependency>
 <dependency>
 <groupId>org.aspectj</groupId>
 <artifactId>aspectjweaver</artifactId>
 <version>1.7.0</version>
 </dependency>
</dependencies>

2.  Create the context loader file to manage the autowiring of spring framework

import org.springframework.beans.factory.config.AutowireCapableBeanFactory;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Loader {

ApplicationContext context;

public Loader(String fileName, Object object) {

// TODO Auto-generated constructor stub

context = new ClassPathXmlApplicationContext(fileName);

if (context != null) {

AutowireCapableBeanFactory beanFactory = context

.getAutowireCapableBeanFactory();

beanFactory.autowireBeanProperties(object,

AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT, false);

}

}

}

3.  Create the applicationContext-spring.xml and put it in your classpath

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:context="http://www.springframework.org/schema/context"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"

xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd

http://www.springframework.org/schema/data/neo4j http://www.springframework.org/schema/data/neo4j/spring-neo4j-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

<context:spring-configured />

<context:annotation-config />

<context:component-scan base-package="Activiti.Basic" />

<bean id="dataSource"

class="org.springframework.jdbc.datasource.SimpleDriverDataSource">

<property name="driverClass" value="com.mysql.jdbc.Driver" />

<property name="url" value="jdbc:mysql://localhost:3306/activiti" />

<property name="username" value="root" />

<property name="password" value="**********" />

</bean>

<bean id="transactionManager"

class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<property name="dataSource" ref="dataSource"></property>

</bean>

<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">

<property name="databaseType" value="mysql" />

<property name="dataSource" ref="dataSource" />

<property name="databaseSchemaUpdate" value="true" />

<property name="history" value="full" />

<property name="jobExecutorActivate" value="true" />

<property name="deploymentResources" value="classpath*:*.bpmn" />

<property name="transactionManager" ref="transactionManager"/>

</bean>

<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">

<property name="processEngineConfiguration" ref="processEngineConfiguration" />

</bean>

<bean id="repositoryService" factory-bean="processEngine"

factory-method="getRepositoryService" />

<bean id="runtimeService" factory-bean="processEngine"

factory-method="getRuntimeService" />

<bean id="taskService" factory-bean="processEngine"

factory-method="getTaskService" />

<bean id="historyService" factory-bean="processEngine"

factory-method="getHistoryService" />

<bean id="managementService" factory-bean="processEngine"

factory-method="getManagementService" />

<bean id="identityService" factory-bean="processEngine"

factory-method="getIdentityService" />

</beans>

4. Create the simple bpm workflow and put it on your classpath


<?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: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="http://www.activiti.org/test">
 <process id="check" name="My process" isExecutable="true">
 <startEvent id="startevent1" name="Start"></startEvent>
 <userTask id="usertask1" name="Check"></userTask>
 <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
 <endEvent id="endevent1" name="End"></endEvent>
 <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="endevent1"></sequenceFlow>
 </process>
 <bpmndi:BPMNDiagram id="BPMNDiagram_check">
 <bpmndi:BPMNPlane bpmnElement="check" id="BPMNPlane_check">
 <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
 <omgdc:Bounds height="35.0" width="35.0" x="110.0" y="170.0"></omgdc:Bounds>
 </bpmndi:BPMNShape>
 <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
 <omgdc:Bounds height="55.0" width="105.0" x="190.0" y="160.0"></omgdc:Bounds>
 </bpmndi:BPMNShape>
 <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
 <omgdc:Bounds height="35.0" width="35.0" x="350.0" y="170.0"></omgdc:Bounds>
 </bpmndi:BPMNShape>
 <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
 <omgdi:waypoint x="145.0" y="187.0"></omgdi:waypoint>
 <omgdi:waypoint x="190.0" y="187.0"></omgdi:waypoint>
 </bpmndi:BPMNEdge>
 <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
 <omgdi:waypoint x="295.0" y="187.0"></omgdi:waypoint>
 <omgdi:waypoint x="350.0" y="187.0"></omgdi:waypoint>
 </bpmndi:BPMNEdge>
 </bpmndi:BPMNPlane>
 </bpmndi:BPMNDiagram>
</definitions>

Simple Workflow

5. In this tutorial in order to make the code cleaner then I created a class to manage the work on activiti

package Activiti.Basic;

import org.activiti.engine.IdentityService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.identity.User;
import org.activiti.engine.impl.db.DbSchemaCreate;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;

public class Runner {

@Autowired
 RepositoryService repositoryService;

@Autowired
 RuntimeService runtimeService;

@Autowired
 TaskService taskService;

@Autowired
 IdentityService identityService;

public void start() {
 if (repositoryService != null) {
 System.out.println("Running");
 String id = runtimeService.startProcessInstanceByKey("check")
 .getProcessInstanceId();
 System.out.println(id);
 }
 }

public void checkUnfinishedExecution() {
for (ProcessInstance temp : runtimeService.createProcessInstanceQuery()

.list()) {

System.out.println(temp.getId());

}

 }

 public void assignTask(String instantID, String assigneeName){
 Task task = taskService.createTaskQuery().processInstanceId(instantID).singleResult();

 task.setAssignee(assigneeName);
 taskService.saveTask(task);
 }

 public void createUser(String name){
 User user = identityService.newUser(name);
 identityService.saveUser(user);
 System.out.println(user.getId()+" -->"+" has been created");
 }

 public void checkAssignTask(String instantID){
 Task task =  taskService.createTaskQuery().processInstanceId(instantID).singleResult();
 System.out.println(task.getName() + " assined To : "+task.getAssignee());
 }

 public void authUser(String name){
 identityService.setAuthenticatedUserId("Rio");
 }

public void checkStatus(String id) {

Task temp = taskService.createTaskQuery().processInstanceId(id)
 .singleResult();
 System.out.println(temp.getName() + " -> " + temp.getId());

 }

public void complete(String id) {
 taskService.complete(id);
 }

 public void complete (String instantID ,String name){
 Task temp = taskService.createTaskQuery().processInstanceId(instantID).singleResult().taskAssignee(name).singleResult();
 taskService.complete(temp.getId());
 }

}

6. Let start the application. I will show you some use case on to run the application as below

Case 1

– Create a process instant of BPM

public class App

{

public static void main( String[] args )

{

Runner runner = new Runner();

new Loader("applicationContext-spring.xml", runner);

runner.start();

}

}

Output : Running
Output : 601 <– The instant ID of the process crated by the activiti

Case 2

Getting the task ID of the last execution in the processinstant 601

public class App

{

public static void main( String[] args )

{

Runner runner = new Runner();

new Loader("applicationContext-spring.xml", runner);

runner.checkStatus("601");

}

}

Output : 604 <– This is the last task execution (task with name “Check”) in the process flow with id 601

Case 3
Create a user with name Rio and assign it to the task with ID = 604 named “Check” in the process flow 601

public class App

{

public static void main( String[] args )

{

Runner runner = new Runner();

new Loader("applicationContext-spring.xml", runner);

runner.createUser("Rio");

runner.assignTask("601", "Rio");

}

}

Case 4

Check if the task has been assigned to Rio

public class App

{

public static void main( String[] args )

{

Runner runner = new Runner();

new Loader("applicationContext-spring.xml", runner);

runner.checkAssignTask("601");

}

}

Output : Check assined To : Rio

OK that all the case. You can follow the step by step by following the case sequence. Hopefully the basic code may help programmer out there …

5 comments

  1. Can u please inform me..what version of M@Eclipse plugin ,you are using in POM..because i am getting an error at this end(POM.xml),,..:(

  2. I am fresher. I have follow this example but when execute the program I am getting null pointer exception at following lines in checkStatus

    Task temp = taskService.createTaskQuery().processInstanceId(id).singleResult();

    1. Hi Minakshi,

      Thanks for the review. There are two possibilities error cause in the checkStatus. First is the “taskService” is null or the “id” given is not found in the processInstantId.

      First check, Ensure your taskService is not null. you can create condition such

      if(taskService != null){
      Task temp = taskService.createTaskQuery().processInstanceId(id).singleResult();
      System.out.println(temp.getName() + ” -> ” + temp.getId());
      }else {
      System.out.println(“Task service is not wired properly, please check your wiring”)
      }

      Second check, Ensure the “id” given is the output of runner.start().

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s