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>
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 …
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),,..:(
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();
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().
please help me where I am going wrong.
Thanks in advance
what would be the project structure.