JBPM4学习笔记

目录

JBPM4学习笔记 1

理解JBPM(java Business Process Management)的基本概念: 1

JBPM简要过程 1

第一课:搭建JBPM4运行环境 1

一、 下载JBPM4.3 1

二、 搭建JBPM4运行环境 1

第二课:管理流程定义 1

一、 流程定义 2

二、 部署(发布)流程定义 2

三、 查看已发布流程 2

四、 删除流程 3

第三课:管理流程实例 3

一、 发起新的流程实例 3

二、 终止流程实例 4

三、 直接删除流程实例 5

四、 查看流程实例列表 5

第四课:介绍活动 5

第五课 实例-设计请假流程 6

一、 请假流程定义设计 6

二、 集成web工程 6

第六课 完善请假流程 8

一、 要求: 8

二、 流程定义设计 8

三、 创建首页 9

四、 deploy.jsp发布流程 12

五、 deletePD.jsp删除流程定义 12

六、 start.jsp启动流程实例 13

七、 checkLogin.jsp检验用户是否登录页面 13

八、 login.jsp用户登录页面 13

九、 doLogin.jsp进行用户登录 13

十、 request.jsp申请请假表单 14

十一、 submit.jsp请假提交页面(提交任务) 14

十二、 manager.jsp经理审批页面 14

十三、 manager_submit.jsp经理审批提交页面 15

十四、 老板审批页面 15

十五、 老板审批提交页面 16

第七课 完成经理驳回功能 16

一、 修改经理审批页面 16

二、 修改经理审批提交页面 16

第八课 组织机构 17

一、 流程定义设计 17

二、 测试代码 18

第九课 监听事件 19

第十课 显示流程定义图片并跟踪当前节点 19

一、 jpdl.xml文件与流程图片打包成zip文件进行发布 19

二、 修改发布流程页面代码 19

三、 建立显示页面 19

四、 加载图片的pic.jsp页面 20

附录一:整合jBPM-4Spring 20

1步:更改jbpm.default.cfg.xml配置文件,将下面的部分注释掉 20

2步:更改jbpm.tx.hibernate.cfg.xml配置文件: 20

3步:在Spring配置文件中写beanprocessEnginetemplate 21

FAQ 问题 21

一、 JBPM4项目和tomcat6.0的兼容问 21

二、 org.hibernate.exception.ConstraintViolationException: could not delete: [org.jbpm.pvm.internal.model.ExecutionImpl#1] 22

三、 Caused by: java.lang.ClassNotFoundException: de.odysseus.el.util.SimpleResolver 22

四、 java.lang.NoClassDefFoundError: javax/el/ExpressionFactory 22

JBPM4学习笔记

理解JBPM(java Business Process Management)的基本概念:

jPDL - JBPM Process Definition Language

JBPM简要过程

1、定义流程(利用JPDL)

2、部署流程(部署到数据库)

3、创建公文并与流程实例绑定

4、可以通过JBPM的接口,触发流程向下流动

5、可以通过JBPM的接口,获得流动到某个用户那里的文档(即待处理任务列表)

6、可以通过JBPM的接口,结束某个用户的任务(这将触发流程继续向下流动)

7、如此、直至结束

jBPM是一个可扩展、灵活的流程引擎, 它可以运行在独立的服务器上或者嵌入任何Java应用中

第一课:搭建JBPM4运行环境

一、 下载JBPM4.3

可以到官方下载,然后直接解压就可以了

doc: 用户手册,javadoc和开发指南 

examples: 用户手册中用到的示例流程 

install: 安装脚本 

lib: 第三方库和一些特定的jBPM依赖库 

src: 源代码 

jbpm.jar: jBPM主库归档

二、 搭建JBPM4运行环境

1、 新建一个Java Project项目

2、 添加依赖库jar

a) jbpm.jar

b) JBPM目录/lib下的所有的jar包,当然了,这里有些是可选的。

3、 建立配置文件(可以复制官方实例下的配置文件)文件位于src目录下

a) jbpm.hibernate.cfg.xml

b) jbpm.cfg.xml

c) logging.properties

4、 为了方便建立流程文件,需要安装eclipase的流程设计器插件

a) 插件位于:JBPM目录/install/src\gpd/jbpm-gpd-site.zip

b) 安装后重新启动Eclipse,要求Eclipse3.5版本以上

这样JBPM的流程设计环境及运行环境建立好了。

第二课:管理流程定义

发布流程定义、

查看流程定义、

删除流程定义

一、 流程定义

首先定义一个流程文件。

二、 部署(发布)流程定义

jBPM内部通过各种服务相互作用。 服务接口可以从ProcessEngine中获得, 它是从Configuration构建的

 * RepositoryService repositoryService = processEngine.getRepositoryService();

 * ExecutionService executionService = processEngine.getExecutionService();

 * TaskService taskService = processEngine.getTaskService();

 * HistoryService historyService = processEngine.getHistoryService();

 * ManagementService managementService = processEngine.getManagementService();

  protected RepositoryService repositoryService;//发布,查看,删除流程

  protected ExecutionService executionService;

  protected ManagementService managementService;

  protected TaskService taskService;

  protected HistoryService historyService;

protected IdentityService identityService;

ProcessEngine processEngine;

public HelloTest(){

processEngine= Configuration.getProcessEngine();

}

@Test

public void testDeploy(){

/*

 * RepositoryService 包含了用来管理发布资源的所有方法

 * 通过其addResourceFromClass方法, 流程定义XML的内容可以从文件, 网址,字符串,输入流或zip输入流中获得

 */

RepositoryService repositoryService = processEngine.getRepositoryService();

//进行实际发布

repositoryService.createDeployment().addResourceFromClasspath("helloworld.jpdl.xml").deploy();

}

三、 查看已发布流程

/** * 获取已发布的流程定义 */

@Test

public void testSearchList(){

RepositoryService repositoryService = processEngine.getRepositoryService();

//获取所有已发布流程列表

List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();

for (ProcessDefinition pd : list){

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

}

}

四、 删除流程

@Test

public void testDelete(){

/*

 * RepositoryService 包含了用来管理发布资源的所有方法

 * 通过其addResourceFromClass方法, 流程定义XML的内容可以从文件, 网址,字符串,输入流或zip输入流中获得

 */

RepositoryService repositoryService = processEngine.getRepositoryService();

//进行实际发布

String deployId = repositoryService.createDeployment().addResourceFromClasspath("helloworld.jpdl.xml").deploy();

System.out.println("deployid = " + deployId);

//获取所有已发布流程列表

List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();

System.out.println(list.size());

/*

 * 删除一个流程定义会把它从数据库中删除。

 * 如果在发布中的流程定义还存在活动的流程实例, 这个方法就会抛出异常。 

 * 如果希望级联删除一个发布中流程定义的 所有流程实例, 可以使用deleteDeploymentCascade

 */

repositoryService.deleteDeploymentCascade(deployId);

list = repositoryService.createProcessDefinitionQuery().list();

System.out.println(list.size());

}

第三课:管理流程实例

发起新流程

执行等待的流程

查看流程实例

终止流程实例

删除流程实例

一、 发起新的流程实例

/**

 * 流程实例管理

 */

public class ProcessInstanceTest {

private ProcessEngine processEngine;

public ProcessInstanceTest(){

processEngine = Configuration.getProcessEngine();

processEngine.getRepositoryService().createDeployment().addResourceFromClasspath("helloworld.jpdl.xml").deploy();

}

/**

 * 创建一个新的流程实例

 */

@Test

public void testProcessInstance(){

/** ExecutionService接口,用来管理流程实例 */

ExecutionService executionService = processEngine.getExecutionService();

/** 根据流程的key来创建一个流程实例 */

ProcessInstance pi = executionService.startProcessInstanceByKey("helloworld");

System.out.println(pi);

//检验流程实例pi,是否结束了

System.out.println(pi.isEnded());

//当流程处理等待时,我们可以手动让其向下运行

//参数是根据流程实例的ID

pi = executionService.signalExecutionById(pi.getId());

System.out.println(pi.isEnded());

}

二、 终止流程实例

/**

 * 直接将流程实例结束

 */

@Test

public void testProcessInstanceEnd(){

/** ExecutionService接口,用来管理流程实例*/

ExecutionService executionService = processEngine.getExecutionService();

/**根据流程的key来创建一个流程实例

*/

ProcessInstance pi = executionService.startProcessInstanceByKey("helloworld");

System.out.println(pi);

//检验流程实例pi,是否结束了

System.out.println(pi.isEnded());

//当流程实例不需要向下进行时,而直接结束流程

//参数:一个流程实例ID,和一个结束流程的理由

executionService.endProcessInstance(pi.getId(), "取消流程实例");

}

三、 直接删除流程实例

/**

 * 直接将流程实例删除

 */

@Test

public void testProcessInstanceDelete(){

/** ExecutionService接口,用来管理流程实例*/

ExecutionService executionService = processEngine.getExecutionService();

/** 根据流程的key来创建一个流程实例 */

ProcessInstance pi = executionService.startProcessInstanceByKey("helloworld");

System.out.println(pi);

//检验流程实例pi,是否结束了

System.out.println(pi.isEnded());

//当流程实例不需要,我们可以直接删除流程实例。并且可以使用级连删除

executionService.deleteProcessInstanceCascade(pi.getId());

}

四、 查看流程实例列表

/**

 * 查看流程实例列表

 * 可以使用

 * executionService.createProcessInstanceQuery().list()

 */

@Test

public void testProcessInstanceList(){

ExecutionService executionService = processEngine.getExecutionService();

ProcessInstance pi = executionService.startProcessInstanceByKey("helloworld");

ProcessInstance pi2 = executionService.startProcessInstanceByKey("helloworld");

//获取流程实例列表

List<ProcessInstance> list = executionService.createProcessInstanceQuery().list();

//循环获取流程实例

for (ProcessInstance processInstance : list){

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

}

}}

第四课:介绍活动

Ø 控制流程的活动

Start开始

End结束

Decision决策

Fork分支

Join结合

Sub-process流程

State等待

task任务

Ø 原子活动

指流程执行到些,并不会做其它的,而是执行一些脚本

Java

Script

Sql

Hql

email

第五课 实例-设计请假流程

一、 请假流程定义设计

二、 集成web工程

1、 加入依赖库

2、 加入配置文件

3、 创建JSP页面。

<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>

<%@ page import="java.util.*,org.jbpm.api.*" %>

<%

String path = request.getContextPath();

String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <base href="<%=basePath%>">

    

    <title>My JSP 'index.jsp' starting page</title>

<meta http-equiv="pragma" content="no-cache">

<meta http-equiv="cache-control" content="no-cache">

<meta http-equiv="expires" content="0">    

<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

<meta http-equiv="description" content="This is my page">

<!--

<link rel="stylesheet" type="text/css" href="styles.css">

-->

  </head>

  

  <body>

  <a href="index.jsp?action=deploy">deploy</a><br/>

  <%

  ProcessEngine processEngine = Configuration.getProcessEngine();

  RepositoryService repositoryService = processEngine.getRepositoryService();

  

  String action = request.getParameter("action");

  if("deploy".equals(action)){

  repositoryService.createDeployment().addResourceFromClasspath("leave.jpdl.xml").deploy();

  else if("remove".equals(request.getParameter("action"))){

  repositoryService.deleteDeploymentCascade(request.getParameter("id"));

  }

  

  List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();

  

  for (ProcessDefinition pd : list){

  

  

 %>

 <%=pd.getId()  %>,<%=pd.getName() %> <a href="index.jsp?action=remove&id=<%=pd.getDeploymentId() %>">remove</a><br/>

 <%

  }

  

  %>

  </body>

</html>

4、 所形成的页面

第六课 完善请假流程

一、 要求:

任务人都可以申请请假,但是需要登录之后,请假申请后提交给经理审批,经理审批如果天数大于3天的还需要老板审批,不大于3天的可以直接结束。

当用户登录后,显示自己待办的任务列表

二、 流程定义设计

流程定义代码如下:

<?xml version="1.0" encoding="gbk"?>

<process name="leave" xmlns="http://jbpm.org/4.3/jpdl">

   <start g="118,32,48,48" name="start1">

      <transition g="-47,-17" name="to 申请" to="申请"/>

   </start>

   <task assignee="#{owner}" form="request.jsp" g="92,125,92,52" name="申请">

      <transition to="经理审批"/>

   </task>

   <task assignee="manager" form="manager.jsp" g="91,223,92,52" name="经理审批">

      <transition g="-23,-12" name="批准" to="exclusive1"/>

      <transition g="44,236;41,154:-6,-11" name="驳回" to="申请"/>

   </task>

   <decision expr="#{day > 3 ? '老板审批' : '结束'}" g="112,320,48,48" name="exclusive1">

      <transition g="-44,-14" name="老板审批" to="老板审批"/>

      <transition g="-47,-17" name="结束" to="end1"/>

   </decision>

   <task assignee="boss" form="boss.jsp" g="271,322,92,52" name="老板审批">

      <transition g="313,467:-47,-17" name="to end1" to="end1"/>

   </task>

   <end g="114,442,48,48" name="end1"/>

</process>

说明:任务标签中的form属性表示该任务所对应的表章,在实例中这些表单我们自己手动建立了。

三、 创建首页

在首页,可以发布流程定义,也可以删除流程定义,并且可以创建一个流程定义实例

代码:

<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>

<%@include file="/checkLogin.jsp" %>

<%@ page import="java.util.*,org.jbpm.api.*,org.jbpm.api.task.*" %>

<%

String path = request.getContextPath();

String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

%>

  <%

  ProcessEngine processEngine = Configuration.getProcessEngine();

  //获取流程定义管理接口

  RepositoryService repositoryService = processEngine.getRepositoryService();

  //获取流程实例管理接口

ExecutionService executionService = processEngine.getExecutionService();

  //获取任务管理接口

  TaskService taskService = processEngine.getTaskService();

  

  String username = (String)session.getAttribute("username");

  

  //索取已发布的流程列表

  List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();

  //索取流程实例列表

  List<ProcessInstance> piList = executionService.createProcessInstanceQuery().list();

  //索取指定人员的任务列表

  List<Task> taskList = taskService.findPersonalTasks(username);  

  %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <base href="<%=basePath%>">

    

    <title>流程管理首页</title>

  </head>  

  <body>

  当前用户:<%=username %> <a href="login.jsp">重新登陆</a><br/>

  <a href="deploy.jsp">发布新流程</a>  

  <hr/>  

  <table border="1">

<tr>

<td colspan="6" align="center">已发布流程定义</td>

</tr>

<tr>

<td>序号</td>

<td>流程ID</td>

<td>流程名称</td>

<td>流程版本</td>

<td>Key</td>

<td><span> </span></td>

</tr>

<%

for (int i = 0; i < list.size(); i++){

ProcessDefinition pd = (ProcessDefinition)list.get(i);

%>

<tr>

<td><%=i+1 %></td>

<td><%=pd.getId() %></td>

<td><%=pd.getName() %></td>

<td><%=pd.getVersion() %></td>

<td><%=pd.getKey()%></td>

<td>

<a href="deletePD.jsp?deployId=<%=pd.getDeploymentId() %>">remove</a>|

<a href="start.jsp?key=<%=pd.getKey() %>">start</a>

</td>

</tr>

<%

}

%>

  </table>

  <hr/>

  

  <table border="1">

  <tr>

  <td colspan="5">流程实例</td>

  </tr>

  <tr>

  <td>序号</td>

  <td>流程实例ID</td>

  <td>活动</td>

  <td>状态</td>

  <td><span> </span></td>

  </tr>

  <%

  for(int i = 0; i < piList.size(); i++){

  ProcessInstance pi = (ProcessInstance)piList.get(i);

  %>

  <tr>

  <td><%=i + 1 %></td>

  <td><%=pi.getId() %></td>

  <td><%=pi.findActiveActivityNames() %></td>

  <td><%=pi.getState() %></td>

  <td>

  <a href="#"><span>查看</span></a>

  </td>

  </tr>  

  <%

  }

  %>

  </table>

  <hr/>

  <table border="1">

  <tr>

  <td colspan="5">待办任务列表</td>

  </tr>

  <tr>

  <td>序号</td>

  <td>任务ID</td>

  <td>任务名称</td>

  <td>当前者</td>

  <td> </td>

  </tr>

  <%

  for (int i = 0 ; i < taskList.size(); i++){

  Task task = (Task)taskList.get(i);

  %>

  <tr>

  <td><%=i + 1 %></td>

  <td><%=task.getId() %></td>

  <td><%=task.getName() %></td>

  <td><%=task.getAssignee() %></td>

  <td>

  <a href="<%=task.getFormResourceName()%>?taskId=<%=task.getId() %>">查看</a>

  </td>

  </tr>

  <%

  }

  %>

  </table>

  </body>

</html>

首页的界面:

四、 deploy.jsp发布流程

<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>

<%@ page import="java.util.*,org.jbpm.api.*,org.jbpm.api.task.*" %>

  <%  

  ProcessEngine processEngine = Configuration.getProcessEngine();

  //获取流程定义管理接口

  RepositoryService repositoryService = processEngine.getRepositoryService();

  repositoryService.createDeployment().addResourceFromClasspath("leave.jpdl.xml").deploy();

  response.sendRedirect("index.jsp");

  %>

五、 deletePD.jsp删除流程定义

<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>

<%@ page import="java.util.*,org.jbpm.api.*,org.jbpm.api.task.*" %>

<%

ProcessEngine processEngine = Configuration.getProcessEngine();

RepositoryService repositoryService = processEngine.getRepositoryService();

String deployId = request.getParameter("deployId");

repositoryService.deleteDeploymentCascade(deployId);

response.sendRedirect("index.jsp");

%>

六、 start.jsp启动流程实例

<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>

<%@ page import="java.util.*,org.jbpm.api.*,org.jbpm.api.task.*"%>

<%

ProcessEngine processEngine = Configuration.getProcessEngine();

ExecutionService executionService = processEngine

.getExecutionService();

Map map = new HashMap();

map.put("owner", session.getAttribute("username"));

executionService.startProcessInstanceByKey(request

.getParameter("key"), map);

response.sendRedirect("index.jsp");

%>

七、 checkLogin.jsp检验用户是否登录页面

因为,在创建流程实例时,需要一个用户,因此需要检验用户是否登录

<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>

<%

if (session.getAttribute("username") == null){

//如果用户没有登录,则跳转到登录页面进行用户登录

//因为用户没有登录是没有办法获取待办任务列表

response.sendRedirect("login.jsp");

}

%>

八、 login.jsp用户登录页面

<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <base href="<%=basePath%>">    

    <title>登录</title>

  </head>  

  <body>

   <br>

   <form action="doLogin.jsp" method="post">

   用户名:<input name="username"><br/>

   <input type="submit" value="用户登录"/>

   </form>

  </body>

</html>

九、 doLogin.jsp进行用户登录

<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>

<%

String username = request.getParameter("username");

if (null == username){response.sendRedirect("login.jsp");}

session.setAttribute("username", username);

response.sendRedirect("index.jsp");

%>

十、 request.jsp申请请假表单

<html>

  <head>

    <base href="<%=basePath%>">

    <title>My JSP 'reqeust.jsp' starting page</title>

  </head>  

  <body>

   <fieldset>

   <legend>申请</legend>

   <form action="submit.jsp" method="post">

   <input type="hidden" name="taskId" value="${param.taskId }"/>

   申请人:<input name="owner" value="${sessionScope['username']}"><br/>

   请假时间:<input name="day" value=""/><br/>

   请假原因:<textarea name="reason"></textarea><br/>

   <input type="submit">

   </form>

   </fieldset>   

  </body>

</html>

十一、 submit.jsp请假提交页面(提交任务)

<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>

<%@ page import="java.util.*,org.jbpm.api.*,org.jbpm.api.task.*" %>

  <%  

  ProcessEngine processEngine = Configuration.getProcessEngine();

//获取任务管理接口

TaskService taskService = processEngine.getTaskService();

String taskId = request.getParameter("taskId");

String ower = request.getParameter("owner");

int day = Integer.parseInt(request.getParameter("day"));

String reason = request.getParameter("reason");

Map map = new HashMap();

map.put("day", day);

map.put("reason",reason);

taskService.completeTask(taskId, map);

response.sendRedirect("index.jsp");  

  %>

十二、 manager.jsp经理审批页面

<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>

<%@ page import="java.util.*,org.jbpm.api.*,org.jbpm.api.task.*" %>

  <%  

  ProcessEngine processEngine = Configuration.getProcessEngine();

  TaskService taskService = processEngine.getTaskService();

  String taskId = request.getParameter("taskId");

  Task task = taskService.getTask(taskId);

  %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <base href="<%=basePath%>">    

    <title>My JSP 'manager.jsp' starting page</title>

  </head>  

  <body>

<fieldset>

<legend>经理审批</legend>

<form action="manager_submit.jsp" method="post">

<input type="hidden" name="taskId" value="${param.taskId}">

申请人:<%=taskService.getVariable(taskId,"owner"%><br/>

申请天数:<%=taskService.getVariable(taskId,"day"%><br/>

申请原因:<%=taskService.getVariable(taskId,"reason"%><br/>

<input type="submit" value="批准"/>

<input type="submit" value="驳回"/>

</form>

</fieldset>

  </body>

</html>

十三、 manager_submit.jsp经理审批提交页面

<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>

<%@ page import="java.util.*,org.jbpm.api.*,org.jbpm.api.task.*" %>

  <%  

  ProcessEngine processEngine = Configuration.getProcessEngine();

//获取任务管理接口

TaskService taskService = processEngine.getTaskService();

String taskId = request.getParameter("taskId");

taskService.completeTask(taskId,"批准");

response.sendRedirect("index.jsp");  

  %>

十四、 老板审批页面

<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>

<%@ page import="java.util.*,org.jbpm.api.*,org.jbpm.api.task.*" %>

<%

ProcessEngine processEngine = Configuration.getProcessEngine();

TaskService taskService = processEngine.getTaskService();

String taskId = request.getParameter("taskId");

Task task = taskService.getTask(taskId);

%>  

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>Insert title here</title>

</head>

<body>

  <fieldset>

    <legend>老板审核</legend>

    <form action="submit_boss.jsp" method="post">

      <input type="hidden" name="taskId" value="${param.taskId}">

      申请人:<%=taskService.getVariable(taskId, "owner"%><br/>

  请假时间:<%=taskService.getVariable(taskId, "day"%><br/>

    请假原因:<%=taskService.getVariable(taskId, "reason"%><br/>

    <input type="submit"/>

    </form>

  </fieldset>

</body>

十五、 老板审批提交页面

<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>

<%@ page import="java.util.*,org.jbpm.api.*,org.jbpm.api.task.*" %>

  <%  

  ProcessEngine processEngine = Configuration.getProcessEngine();

//获取任务管理接口

TaskService taskService = processEngine.getTaskService();

String taskId = request.getParameter("taskId");

taskService.completeTask(taskId);

response.sendRedirect("index.jsp");

  %>

第七课 完成经理驳回功能

一、  修改经理审批页面

<fieldset>

<legend>经理审批</legend>

<form action="manager_submit.jsp" method="post">

<input type="hidden" name="taskId" value="${param.taskId}">

申请人:<%=taskService.getVariable(taskId,"owner"%><br/>

申请天数:<%=taskService.getVariable(taskId,"day"%><br/>

申请原因:<%=taskService.getVariable(taskId,"reason"%><br/>

<input name="r" type="submit" value="批准"/>

<input name="r" type="submit" value="驳回"/>

</form>

</fieldset>

加入一个参数,传入到审批提交页面,以告诉提交页面是批准还是驳回

二、 修改经理审批提交页面

  <%  

request.setCharacterEncoding("GB18030");

//response.setContentType("text/html;charset=GB18030");  

  ProcessEngine processEngine = Configuration.getProcessEngine();

//获取任务管理接口

TaskService taskService = processEngine.getTaskService();

String taskId = request.getParameter("taskId");

String r = request.getParameter("r");

taskService.completeTask(taskId,r);

response.sendRedirect("index.jsp");  

  %>

说明:当任务有多个走向时,在提交任务时需要指定任务下一个走向的路径。

   <task assignee="manager" form="manager.jsp" g="91,223,92,52" name="经理审批">

      <transition g="-23,-12" name="批准" to="exclusive1"/>

      <transition g="44,236;41,154:-6,-11" name="驳回" to="申请"/>

   </task>

以上务有“批准”和“驳回”两条路径,因此在提交时需要指明走向如下 

taskService.completeTask(taskId,批准);

taskService.completeTask(taskId,驳回);

这样就完成了批准和驳回功能了

第八课 组织机构

Ø 用户

Ø 用户组

Ø 成员关系

一个任务可以分配给一个用户组,然后用户组中的用户可以竟争的方式来完成任务

以下为实例

一、 流程定义设计

二、 测试代码

public class TaskTest {

private ProcessEngine processEngine;

public TaskTest() {

processEngine = Configuration.getProcessEngine();

// 获取组织机构服务接口

IdentityService identityService = processEngine.getIdentityService();

// 创建一个用户组

identityService.createGroup("dev");

// 创建用户user1user2

identityService.createUser("user1""user1""user1");

identityService.createUser("user2""user2""user2");

// 建立用户与用户组的关系,也就是将用户加入到某一个用户组

// 以下是将用户user1user2加入到dev用户组中

identityService.createMembership("user1""dev");

identityService.createMembership("user2""dev");

}

@Test

public void testTask() {

RepositoryService repositoryService = processEngine

.getRepositoryService();

TaskService taskService = processEngine.getTaskService();

ExecutionService executionService = processEngine.getExecutionService();

// 发布流程

String deploymentId = repositoryService.createDeployment()

.addResourceFromClasspath("task.jpdl.xml").deploy();

//启动一个新的实例

executionService.startProcessInstanceByKey("task");

//索取用户组中指定用户的任务列表的数量

System.out.println(taskService.findGroupTasks("user1").size());

System.out.println(taskService.findGroupTasks("user2").size());

//索取用户组中指定用户的任务列表

List<Task> groupTaskList = taskService.findGroupTasks("user1");

//注意:taskService.findPersonalTasks(username);是获取指定用户的任务列表,

//取得任务列表中第一个任务

Task task = groupTaskList.get(0);

//用户user1接受任务

taskService.takeTask(task.getId(), "user1");

//提交任务

taskService.completeTask(task.getId());

}

}

第九课 监听事件

流程实例

启动

结束

活动

开始

结束

事件监听:是工作流程一个功能回调一个主要方法

第十课 显示流程定义图片并跟踪当前节点

一、 将jpdl.xml文件与流程图片打包成zip文件进行发布

文件名要求与流程文件名一样

二、 修改发布流程页面代码

<%@page import="java.util.*,org.jbpm.api.*,java.util.zip.*"%>  

<%

  ProcessEngine processEngine = Configuration.getProcessEngine();

  RepositoryService repositoryService = processEngine

  .getRepositoryService();  //repositoryService.createDeployment().addResourceFromClasspath("leave.jpdl.xml").deploy();

  ZipInputStream zis = new ZipInputStream(this.getClass()

  .getResourceAsStream("/leave.zip"));

  repositoryService.createDeployment()

  .addResourcesFromZipInputStream(zis).deploy();

  response.sendRedirect("index.jsp");

  %>

三、 建立显示页面

<%@ page language="java" contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

<%@page import="org.jbpm.api.*,java.util.*,org.jbpm.api.model.*" %>

<%

String id = request.getParameter("id");

ProcessEngine processEngine = Configuration.getProcessEngine();

RepositoryService repositoryService = processEngine.getRepositoryService();

ExecutionService executionService = processEngine.getExecutionService();

ProcessInstance processInstance = executionService.findProcessInstanceById(id);

Set<String> activityNames = processInstance.findActiveActivityNames();

ActivityCoordinates ac = repositoryService.getActivityCoordinates(processInstance.getProcessDefinitionId(),activityNames.iterator().next());

%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>Insert title here</title>

</head>

<body>

<img src="pic.jsp?id=<%=id %>" style="position:absolute;left:0px;top:0px;">

<div style="position:absolute;border:1px solid red;left:<%=ac.getX()%>px;top:<%=ac.getY()%>px;width:<%=ac.getWidth()%>px;height:<%=ac.getHeight()%>px;"></div>

</body>

</html>

四、 加载图片的pic.jsp页面

<%@page import="org.jbpm.api.*,java.io.*"%>

<%

ProcessEngine processEngine = Configuration.getProcessEngine();

RepositoryService repositoryService = processEngine

.getRepositoryService();

ExecutionService executionService = processEngine

.getExecutionService();

String id = request.getParameter("id");

ProcessInstance processInstance = executionService

.findProcessInstanceById(id);

String processDefinitionId = processInstance

.getProcessDefinitionId();

ProcessDefinition processDefinition = repositoryService

.createProcessDefinitionQuery().processDefinitionId(

processDefinitionId).uniqueResult();

InputStream inputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(),"leave.png");

byte[] b = new byte[1024];

int len = -1;

while ((len = inputStream.read(b, 0, 1024)) != -1) {

response.getOutputStream().write(b, 0, len);

}

%>

附录一:整合jBPM-4Spring

1步:更改jbpm.default.cfg.xml配置文件,将下面的部分注释掉

    <!--

        <hibernate-configuration>

            <cfg resource="jbpm.hibernate.cfg.xml" />

        </hibernate-configuration>

        <hibernate-session-factory />

    -->

          注释的部分是在jBPM4中创建了sessionFactory,而我们只需要一个sessionFactory。既然要将jBPM4Spring的整合,那就希望由Spring来统一管理sessionFactory和事务,在Spring的配置文件中构造一个sessionFactory。 ProcessEnginejBPM4Facade模式,一切由它与外部交互,

2步:更改jbpm.tx.hibernate.cfg.xml配置文件:

    <standard-transaction-interceptor/>

          改为

    <spring-transaction-interceptor />

          然后将

    <transaction/>

    <hibernate-session/>          改为

    <hibernate-session current="true"/>

   这部分修改是将jBPM4创建的spring事务和hibernatesession改成从当前的ThreadLocal中获得session和事务。

3步:在Spring配置文件中写beanprocessEnginetemplate

    <bean id="jbpmConfiguration" class="org.jbpm.pvm.internal.cfg.SpringConfiguration">

        <constructor-arg value="jbpm/jbpm.cfg.xml" />

    </bean>

    <bean id="processEngine" factory-bean="jbpmConfiguration" factory-method="buildProcessEngine" />

          processEngine直接使用factory-bean指向jbpmConfiguration,也就是 org.jbpm.pvm.internal.cfg.SpringConfiguration,并从SpringConfiguration的 buildProcessEngine中获得。

FAQ 问题

一、 JBPM4项目和tomcat6.0的兼容问

基于JBPM4的web项目jsp页面发布出错,错误如下:
       exception 

javax.servlet.ServletException: java.lang.LinkageError: loader constraint violation: when resolving interface method "javax.servlet.jsp.JspApplicationContext.getExpressionFactory()Ljavax/el/ExpressionFactory;" the class loader (instance of org/apache/jasper/servlet/JasperLoader) of the current class, org/apache/jsp/OnDuty/wfmanage_jsp, and the class loader (instance of org/apache/catalina/loader/StandardClassLoader) for resolved class, javax/servlet/jsp/JspApplicationContext, have different Class objects for the type javax/el/ExpressionFactory used in the signature

org.apache.jasper.servlet.JspServlet.service(JspServlet.java:275)

javax.servlet.http.HttpServlet.service(HttpServlet.java:717)

 root cause 

java.lang.LinkageError: loader constraint violation: when resolving interface method "javax.servlet.jsp.JspApplicationContext.getExpressionFactory()Ljavax/el/ExpressionFactory;" the class loader (instance of org/apache/jasper/servlet/JasperLoader) of the current class, org/apache/jsp/OnDuty/wfmanage_jsp, and the class loader (instance of org/apache/catalina/loader/StandardClassLoader) for resolved class, javax/servlet/jsp/JspApplicationContext, have different Class objects for the type javax/el/ExpressionFactory used in the signature

org.apache.jsp.OnDuty.wfmanage_jsp._jspInit(wfmanage_jsp.java:27)

org.apache.jasper.runtime.HttpJspBase.init(HttpJspBase.java:52)

org.apache.jasper.servlet.JspServletWrapper.getServlet(JspServletWrapper.java:159)

org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:329)

org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)

org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)

javax.servlet.http.HttpServlet.service(HttpServlet.java:717)

原因是项目中WEB-INF\lib中的三个jar包(juel.jar, juel-engine.jar, juel-impl.jar)和tomcat6下lib中jar包(el-api.jar)冲突

解决方法:

方法一:换成tomcat5.5 一点问题也没有了

方法二:将juel.jar, juel-engine.jar, juel-impl.jar这三个包复制到tomcat6下lib中,并删除原来的el-api.jar,切记要把WEB-INF\lib中的juel.jar, juel-engine.jar, juel-impl.jar删除。不然还是要冲突

二、 org.hibernate.exception.ConstraintViolationException: could not delete: [org.jbpm.pvm.internal.model.ExecutionImpl#1]

方法:连接Mysql5时,jBPM4运行到 End结点时的错误,把 hibernate.dialect 改为 org.hibernate.dialect.MySQLInnoDBDialect

三、 Caused by: java.lang.ClassNotFoundException: de.odysseus.el.util.SimpleResolver 

原因:tomcat 6.0下面的el-api.jar
解决方法:删掉tomcat6el.jar,加入juel.jar,juel-impl.jar,juel-engine.jar 
juel.jar,juel-impl.jar,juel-engine.jar 可以在jbmp4.0lib目录下找到,

四、 java.lang.NoClassDefFoundError: javax/el/ExpressionFactory

原因:tomcat/lib下的el-api.jar被删除
解决方法:把名为javaee.jar包放到tomcat/lib里面就可以了,可以在myeclipse下找到,

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值