SSH整合JBPM4.4
第一步:导入所需jar包:
所需的jar包(使用了hibernate annotation和struts2的convention-plugin,可能有多余的包,没做清理):
第二步:修改jbpm配置文件:
1、src目录下建立jbpm.cfg.xml(注意注释部分)
<?xml version="1.0" encoding="UTF-8"?> <jbpm-configuration> <process-engine-context> <string name="spring.cfg" value="applicationContext.xml" /> </process-engine-context> <import resource="jbpm.default.cfg.xml" /> <import resource="jbpm.tx.spring.cfg.xml" /> <import resource="jbpm.jpdl.cfg.xml" /> <import resource="jbpm.bpmn.cfg.xml" /> <import resource="jbpm.identity.cfg.xml" /> <import resource="jbpm.businesscalendar.cfg.xml" /> <import resource="jbpm.console.cfg.xml" /> <import resource="jbpm.spring.default.cfg.xml"/> <!-- <import resource="jbpm.jobexecutor.cfg.xml" /> --> </jbpm-configuration>
2、src目录下建立jbpm.spring.default.cfg.xml
<?xml version="1.0" encoding="UTF-8"?> <jbpm-configuration> <process-engine-context> <repository-service /> <repository-cache /> <execution-service /> <history-service /> <management-service /> <identity-service /> <task-service /> <!-- <hibernate-configuration> <cfg resource="jbpm.hibernate.cfg.xml" /> </hibernate-configuration> <hibernate-session-factory /> --> <script-manager default-expression-language="juel" default-script-language="juel" read-contexts="execution, environment, process-engine" write-context=""> <script-language name="juel" factory="org.jbpm.pvm.internal.script.JuelScriptEngineFactory" /> </script-manager> <authentication /> <id-generator /> <types resource="jbpm.variable.types.xml" /> <address-resolver /> <business-calendar> <monday hours="9:00-12:00 and 12:30-17:00"/> <tuesday hours="9:00-12:00 and 12:30-17:00"/> <wednesday hours="9:00-12:00 and 12:30-17:00"/> <thursday hours="9:00-12:00 and 12:30-17:00"/> <friday hours="9:00-12:00 and 12:30-17:00"/> <holiday period="01/07/2008 - 31/08/2008"/> </business-calendar> <mail-template name='task-notification'> <to users="${task.assignee}"/> <subject>${task.name}</subject> <text><![CDATA[Hi ${task.assignee}, Task "${task.name}" has been assigned to you. ${task.description} Sent by JBoss jBPM ]]></text> </mail-template> <mail-template name='task-reminder'> <to users="${task.assignee}"/> <subject>${task.name}</subject> <text><![CDATA[Hey ${task.assignee}, Do not forget about task "${task.name}". ${task.description} Sent by JBoss jBPM ]]></text> </mail-template> </process-engine-context> <transaction-context> <repository-session /> <db-session /> <message-session /> <timer-session /> <history-session /> <mail-session> <mail-server> <session-properties resource="jbpm.mail.properties" /> </mail-server> </mail-session> </transaction-context> </jbpm-configuration>
第三步:修改Spring配置文件
1、applicationContext.xml中加入springHelper配置,作为jbpm processEngine的factory bean
<bean id="springHelper" class="org.jbpm.pvm.internal.processengine.SpringHelper"> <property name="jbpmCfg" value="jbpm.cfg.xml" /> </bean>
2、applicationContext.xml中加入processEngine配置,并以此为factory bean创建JBPM本身的各种Service
<bean id="processEngine" factory-bean="springHelper" factory-method="createProcessEngine" /> <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService"/> <bean id="executionService" factory-bean="processEngine" factory-method="getExecutionService"/> <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService"/> <bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService"/> <bean id="identityService" factory-bean="processEngine" factory-method="getIdentityService"/>
3、applicationContext.xml的hibernate配置中加入jbpm所需的hbm.xml配置
<property name="mappingLocations"> <list> <value>classpath:jbpm.execution.hbm.xml</value> <value>classpath:jbpm.history.hbm.xml</value> <value>classpath:jbpm.identity.hbm.xml</value> <value>classpath:jbpm.repository.hbm.xml</value> <value>classpath:jbpm.task.hbm.xml</value> </list> </property>
4、完整的applicationContext.xml(包括其余DataSource、SessionFacotry、事务控制等)
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd" default-lazy-init="true"> <import resource="serviceContext.xml" /> <bean id="springHelper" class="org.jbpm.pvm.internal.processengine.SpringHelper"> <property name="jbpmCfg" value="jbpm.cfg.xml" /> </bean> <bean id="processEngine" factory-bean="springHelper" factory-method="createProcessEngine" /> <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService"/> <bean id="executionService" factory-bean="processEngine" factory-method="getExecutionService"/> <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService"/> <bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService"/> <bean id="identityService" factory-bean="processEngine" factory-method="getIdentityService"/> <bean id="mainDataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close"> <property name="driverClass" value="oracle.jdbc.driver.OracleDriver" /> <property name="jdbcUrl" value="jdbc:oracle:thin:@XXXXX:1521:XE" /> <property name="username" value="jbpm4" /> <property name="password" value="jbpm" /> <property name="idleConnectionTestPeriod" value="60" /> <property name="idleMaxAge" value="240" /> <property name="maxConnectionsPerPartition" value="60" /> <property name="minConnectionsPerPartition" value="20" /> <property name="partitionCount" value="3" /> <property name="acquireIncrement" value="10" /> <property name="preparedStatementCacheSize" value="50" /> <property name="statementsCachedPerConnection" value="30" /> <property name="releaseHelperThreads" value="3" /> </bean> <bean id="dataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy"> <property name="targetDataSource"> <ref local="mainDataSource" /> </property> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource"> <ref bean="dataSource" /> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.Oracle9iDialect</prop> <prop key="hibernate.show_sql">true</prop> </props> </property> <property name="mappingLocations"> <list> <value>classpath:jbpm.execution.hbm.xml</value> <value>classpath:jbpm.history.hbm.xml</value> <value>classpath:jbpm.identity.hbm.xml</value> <value>classpath:jbpm.repository.hbm.xml</value> <value>classpath:jbpm.task.hbm.xml</value> </list> </property> <property name="annotatedClasses"> <list> <value>com.fish119.jssh.pojo.Test</value> </list> </property> </bean> <!-- 事务配置开始 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!--事务配置--> <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager"> <ref bean="transactionManager" /> </property> <!-- 配置事务属性 --> <property name="transactionAttributes"> <props> <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop> <prop key="delete*">PROPAGATION_REQUIRED</prop> <prop key="insert*">PROPAGATION_REQUIRED,-Exception</prop> <prop key="add*">PROPAGATION_REQUIRED,-Exception</prop> <prop key="update*">PROPAGATION_REQUIRED,-Exception</prop> <prop key="save*">PROPAGATION_REQUIRED,-Exception</prop> <prop key="*Save*">PROPAGATION_REQUIRED,-Exception</prop> <prop key="exchange*">PROPAGATION_REQUIRED,-Exception</prop> <prop key="remove*">PROPAGATION_REQUIRED,-Exception</prop> <prop key="set*">PROPAGATION_REQUIRED,-Exception</prop> <prop key="Test*">PROPAGATION_REQUIRED,-Exception</prop> <prop key="*Test">PROPAGATION_REQUIRED,-Exception</prop> </props> </property> </bean> <bean id="autoproxy" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames"> <list> <value>*Service</value> </list> </property> <property name="interceptorNames"> <list> <value>transactionInterceptor</value> </list> </property> </bean> <!-- 事务配置结束 --> <bean id="testDAO" class="com.fish119.jssh.dao.TestDAO" autowire="byType"> <property name="sessionFactory"> <ref bean="sessionFactory" /> </property> </bean> </beans>
第四步:配置Struts2(使用了convention plugin)
struts.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <constant name="struts.objectFactory" value="spring" /> <!-- <constant name="struts.objectFactory.spring.autoWire" value="type"/> --> <constant name="struts.devMode" value="true" /> <constant name="struts.convention.classes.reload" value="true" /> <!-- 结果资源所在路径 --> <constant name="struts.convention.result.path" value="/" /> <!-- 默认action所在的包 --> <constant name="struts.convention.default.parent.package" value="myPackage" /> <!-- 不被convention组件扫描的包 --> <!-- <constant name="struts.convention.exclude.packages" value=""/> --> <package name="myPackage" extends="json-default"> <global-results> <result name="exception">/error.jsp</result> <result name="error">/error.jsp</result> <result name="none">/error.jsp</result> <result name="login">/login.jsp</result> </global-results> <global-exception-mappings> <exception-mapping result="exception" exception="java.lang.Exception"> </exception-mapping> </global-exception-mappings> </package> </struts>
第五步:测试
1、建立action类:IndexAction
public class IndexAction extends BaseAction{ private static final long serialVersionUID = 1L; ProcessEngine processEngine; RepositoryService repositoryService; ExecutionService executionService; TaskService taskService; HistoryService historyService; IdentityService identityService; public ProcessEngine getProcessEngine(){ return processEngine; } public void setProcessEngine(ProcessEngine processEngine){ this.processEngine = processEngine; } public RepositoryService getRepositoryService(){ return repositoryService; } public void setRepositoryService(RepositoryService repositoryService){ this.repositoryService = repositoryService; } public ExecutionService getExecutionService(){ return executionService; } public void setExecutionService(ExecutionService executionService){ this.executionService = executionService; } public TaskService getTaskService(){ return taskService; } public void setTaskService(TaskService taskService){ this.taskService = taskService; } public HistoryService getHistoryService(){ return historyService; } public void setHistoryService(HistoryService historyService){ this.historyService = historyService; } public IdentityService getIdentityService(){ return identityService; } public void setIdentityService(IdentityService identityService){ this.identityService = identityService; } public String execute(){ System.out.println("processEngine:" + this.getProcessEngine()); System.out.println("repositoryService:" + this.getRepositoryService()); System.out .println("executionServcie:" + this.getExecutionService()); System.out.println("taskService:" + this.getTaskService()); System.out.println("historyService:" + this.getHistoryService()); return SUCCESS; } }
2、jbpm核心代码:
package com.jabberchina.jbpm4.utils; import java.util.List; import java.util.Map; import java.util.Set; import org.jbpm.api.Execution; import org.jbpm.api.ExecutionService; import org.jbpm.api.HistoryService; import org.jbpm.api.ManagementService; import org.jbpm.api.ProcessEngine; import org.jbpm.api.ProcessInstance; import org.jbpm.api.RepositoryService; import org.jbpm.api.TaskService; import org.jbpm.api.model.ActivityCoordinates; import org.jbpm.api.task.Task; import com.jabberchina.core.Page; /** * @author guwh * @version 创建时间:2011-11-7 下午03:49:35 类说明 jbpm操作数据库模板类 */ public class Jbpm4Utils { private ProcessEngine processEngine; private RepositoryService repositoryService = null; private ExecutionService executionService = null; private TaskService taskService = null; private HistoryService historyService = null; private ManagementService managementService = null; public Jbpm4Utils() { } /** * 部署流程到数据库 * * @param resourceName * 资源文件名字 比如(com/jabberchina/jbpm/jpdl/process.jpdl.xml) * @return 返回流程定义id(格式:key-version) */ public String Deploy(String resourceName) { return repositoryService.createDeployment().addResourceFromClasspath( resourceName).deploy(); } /** * 创建一个新的流程实例 * * @param processDefinitionKey * (process.jpdl.xml中process标签的key) * @param processInstanceKey * (用户给的key,比如一个请假单的id) * @return 流程实例 */ public ProcessInstance startProcessInstance(String processDefinitionKey, String processInstanceKey) { return executionService.startProcessInstanceByKey(processDefinitionKey, processInstanceKey); } /** * 创建一个新的流程实例 * * @param processDefinitionKey * (process.jpdl.xml中process标签的key) * @return 流程实例 */ public ProcessInstance startProcessInstance(String processDefinitionKey) { return executionService.startProcessInstanceByKey(processDefinitionKey); } /** * 创建一个新的流程实例 * * @param processDefinitionKey * (process.jpdl.xml中process标签的key) * @param variables * 该流程实例要用到的变量 * @param processInstanceKey * (用户给定的业务key) * @return */ public ProcessInstance startProcessInstance(String processDefinitionKey, Map<String, ?> variables, String processInstanceKey) { return executionService.startProcessInstanceByKey(processDefinitionKey, variables, processInstanceKey); } /** * 提交任务(适合于第一个任务自动完成) * * @param processInstanceId * 任务id */ public void completeTaskByPid(String processInstanceId, String outcome, Map<String, ?> variables) { Task task = taskService.createTaskQuery().processInstanceId( processInstanceId).uniqueResult(); String taskId = task.getId(); taskService.completeTask(taskId, outcome, variables); } /** * 提交任务(适合于第一个任务自动完成) * * @param processInstanceId * 任务id */ public void completeTaskByPid(String processInstanceId, String outcome) { Task task = taskService.createTaskQuery().processInstanceId( processInstanceId).uniqueResult(); String taskId = task.getId(); taskService.completeTask(taskId, outcome); } /** * 提交任务 * * @param taskId * 任务id */ public void completeTask(String taskId) { taskService.completeTask(taskId); } /** * 将任务流转到指定名字的流程中去 * * @param taskId * @param outcome */ public void completeTask(String taskId, String outcome) { taskService.completeTask(taskId, outcome); } /*** * 将任务流转到指定名字的流程中去,并带有参数变量 * * @param taskId * @param outcome * @param variables */ public void completeTask(String taskId, String outcome, Map<String, ?> variables) { taskService.completeTask(taskId, outcome, variables); } /** * 根据key获取流程实例 * * @param key * * @return 返回查找到得流程实例,没有返回null */ public ProcessInstance getProcessInstance(String key) { return executionService.createProcessInstanceQuery() .processInstanceKey(key).uniqueResult(); } /** * 根据executionId获取指定的变量值 * * @param executionId * @param variableName * @return */ public Object getVariableByexecutionId(String executionId, String variableName) { return executionService.getVariable(executionId, variableName); } /** * 根据任务id获取指定变量值 * * @param taskId * @param variableName * @return */ public Object getVariableByTaskId(String taskId, String variableName) { return taskService.getVariable(taskId, variableName); } /** * 获取指定用户名字的任务,并分页 * * @param userId * @return */ public Page<Task> findPersonalTasksPage(Page<Task> page, String userId) { int totalCount = (int) taskService.createTaskQuery().assignee(userId) .count(); if (page == null) { page = new Page<Task>(); } List<Task> list = taskService.createTaskQuery().assignee(userId).page( page.getFirst(), page.getPageSize()).list(); if (list == null) return null; page.setResult(list); page.setTotalCount(totalCount); return page; } /*** * 获取要查页的Task列表 * * @param firstResult * @param maxResults * @param userId * @return */ public List<Task> findPersonalTasks(int firstResult, int maxResults, String userId) { return taskService.createTaskQuery().assignee(userId).page(firstResult, maxResults).list(); } /*** * 获取当然任务个数 * * @param userId * @return */ public Long findPersonalTaskCount(String userId) { return taskService.createTaskQuery().assignee(userId).count(); } /** * 根据任务id获取任务 * * @param taskId * @return */ public Task findPersonalTasks(String userId) { return taskService.createTaskQuery().assignee(userId).uniqueResult(); } /** * 根据任务id获取任务 * * @param taskId * @return */ public Task getTask(String taskId) { return taskService.getTask(taskId); } /*** * 将任务重新分配给指定人 * * @param taskId * @param assignee */ public void modifyAssignee(String taskId, String assignee) { taskService.assignTask(taskId, assignee); } /*** * 获取当前活动节点位置 * * @param key * 流程发布时KEY * @param taskId * 当前任务id * @return */ public ActivityCoordinates getActivityCoordinates(String key) { ProcessInstance processInstance = getProcessInstance(key); if (processInstance != null) { Set<String> activityNames = processInstance .findActiveActivityNames(); return repositoryService.getActivityCoordinates(getProcessInstance( key).getProcessDefinitionId(), activityNames.iterator() .next()); } else { return null; } } /** * 根据流程实例id获取 * * @param executionId * @return */ public Execution findExecutionById(String executionId) { return executionService.findExecutionById(executionId); } /*** * 删除流程实例 * * @param processInstanceId */ public void deleteProcessInstanceCascade(String processInstanceId) { executionService.deleteProcessInstanceCascade(processInstanceId); } /** * 彻底删除文件的部署 * * @param deploymentId流程定义id */ public void deleteDeploymentCascade(String deploymentId) { repositoryService.deleteDeploymentCascade(deploymentId); } public ProcessEngine getProcessEngine() { return processEngine; } public void setProcessEngine(ProcessEngine processEngine) { this.processEngine = processEngine; repositoryService = processEngine.getRepositoryService(); executionService = processEngine.getExecutionService(); taskService = processEngine.getTaskService(); historyService = processEngine.getHistoryService(); managementService = processEngine.getManagementService(); } public RepositoryService getRepositoryService() { return repositoryService; } public void setRepositoryService(RepositoryService repositoryService) { this.repositoryService = repositoryService; } public ExecutionService getExecutionService() { return executionService; } public void setExecutionService(ExecutionService executionService) { this.executionService = executionService; } public TaskService getTaskService() { return taskService; } public void setTaskService(TaskService taskService) { this.taskService = taskService; } public HistoryService getHistoryService() { return historyService; } public void setHistoryService(HistoryService historyService) { this.historyService = historyService; } public ManagementService getManagementService() { return managementService; } public void setManagementService(ManagementService managementService) { this.managementService = managementService; } }
3、启动tomcat,访问http://localhost:8080/ProjectName/index。控制台出现以下内容:
processEngine:org.jbpm.pvm.internal.processengine.SpringProcessEngine@2553861
repositoryService:org.jbpm.pvm.internal.repository.RepositoryServiceImpl@22b044e
executionServcie:org.jbpm.pvm.internal.svc.ExecutionServiceImpl@220d12e
taskService:org.jbpm.pvm.internal.svc.TaskServiceImpl@22d9289
historyService:org.jbpm.pvm.internal.svc.HistoryServiceImpl@2257b64
identityService:org.jbpm.pvm.internal.svc.IdentityServiceImpl@223f277
4、可以进一步进行事务测试,建立自己的Service类,添加测试方法,可以看到事务已由Spring统一管理,这里就不提供代码了
本文转自:http://blog.csdn.net/yjboy1982/article/details/6043379
参考文章:http://fish119.iteye.com/blog/779379
http://gwh-08.iteye.com/blog/1567622