jbpm4对与想学习工作流的coder来说,也不会陌生了,基本的介绍我就不多说了,这里有一篇我转载的jbpm4的开发环境配置的文章,没配置好的童鞋可以依照配置一下。好了开始进入正题。
jbpm4在平时使用中需要用的概念大体总结如下:
1、工作流的发布和删除
processEngine:流程引擎,直接通过Configuration.getProcessEngine()获得,是一个静态的方法。
repositoryService:管理流程定义,部署流程的一个类,通过processEngine.getRepositoryService()获得,
可以通过repositoryService.createDeployment().addResourceFromClasspath("leave.jpdl.xml").deploy()来直接部署一个jpdl的流程定义文件。
可以通过repositoryService.createDeployment().addResourcesFromZipInputStream(zis),将一个压缩包的流进行部署。
可以通过createProcessDefinitionQuery().list()来查询当前已经加载的流程定义列表。
可以通过createDeploymentQuery().list()来查询已经部署的流程列表。
可以通过deleteDeployment()或者deleteDeploymentCascade()来删除已经部署的流程,带Cascade的函数会级联删除流程下的子流程。
在请假流程项目中的应用代码如下:
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();解释一下:这里加载的leave.zip是指 编译完成leave.jpdl.xml之后生成了相应的leave.png时候将这两个文件打包之后的zip,至于这样部署的目的是能够通过里面打包的lave.png文件获得对应的流程图,一边在项目后面查看当前流程所处进度时候使用。
2、流程实例的启动、删除、查看进度。
ExecutionService:通过processEngine.getExecutionService(),这个类是负责管理流程运行相关事宜的,
可以通过startProcessInstanceById()来启动一个流程,这个id是通过部署时createProcessDefinitionQuery().list()来获得。
可以通过endProcessInstance来结束一个流程实例,结束之后查看该流程实例的流程图会显示结束状态。
可以通过deleteProcessInstance和deleteProcessInstanceCascade,删除一个流程实例,删除操作的历史记录会jbpm数据库里面可以查看到。
可以通过executionService.createProcessInstanceQuery().list()来获得一个流程实例的list
ProcessInstance:可以通过上面的查询获得,
可以通过getId()获得流程实例的id
可以通过findActiveActivityNames()来获得当前处于激活状态的节点,返回的是一个set集合,因为一个流程可能需要同时需要三个或任意个节点的全部通过才会继续想下走。
可以通过getState()获得当前流程节点的一个状态
STATE_ACTIVE_ROOT:表示在流程图中处于一个“单线(非并发)”的流程节点。
STATE_ACTIVE_CONCURRENT:表示在流程图中处于一个并发的流程节点。
STATE_INACTIVE_CONCURRENT_ROOT:表示在流程图中,当前节点是并发节点的父节点。
STATE_INACTIVE_SCOPE:表示在流程图中,当前节点是一个域流向的父节点(这句话翻译的有点生硬,我也不是很理解,原文是:parent of a scoped execution)。
STATE_INACTIVE_JOIN:表示当前节点会在其他并发节点到达前一直等待。
STATE_SUSPENDED:表示当前节点临时挂起。
STATE_ASYNC:表示当前流程正在执行一个异步的延续,意思就是当前节点已经脱离主流程正在完成一个独立的任务。STATE_ENDED:流程结束。
在请假流程项目中的应用代码如下:
//启动
ProcessEngine processEngine = Configuration.getProcessEngine(); ExecutionService executionService = processEngine .getExecutionService(); Map map = new HashMap(); map.put("owner", session.getAttribute("username")); executionService.startProcessInstanceById(request .getParameter("id"), map);
//删除
ProcessEngine processEngine = Configuration.getProcessEngine(); RepositoryService repositoryService = processEngine.getRepositoryService(); repositoryService.deleteDeploymentCascade(request.getParameter("id"));
//查看流程进度
1.显示整张流程图
<img src="pic.jsp?id=<%=id %>" style="position:absolute;left:0px;top:0px;">
//pic.jsp中的内容。就是将lave。png输出到页面
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); }
2.标出当前流程进度
<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>
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(); //这个ac包含了当前节点在流程图中的坐标和高宽。通过上面的div在leave。png标注出来 ActivityCoordinates ac = repositoryService.getActivityCoordinates(processInstance.getProcessDefinitionId(),activityNames.iterator().next());
3、查看任务、完成任务。
taskService:通过processEngine.getTaskService()获得,这个类负责专门管理任务的,因为一个流程图中的每个节点都是一个任务,在规划流程图时,你可以给买个任务节点分配一定的人来进行处理这个节点的事物。
通过findPersonalTasks()方法获得一个tasklist,该方法需要一个代表用户名的string参数,这个方法是检索的我们在流程图中配置的每个节点的分配人。
Task: 通过tasklist获得
通过getId()和getName()获得任务的的id和名称。
可以通过获得getFormResourceName()获得当前任务节点在流程图中定义的form地址。
可以通过taskService.completeTask(taskId, map)来完成一个任务,使流程继续执行,taskid就是任务id,map里面放置一些参数是你定义当前流程的表达式所需要的参数
在请假流程项目中的应用代码如下:
1、查看任务 这里是经理审批请假申请的代码
ProcessEngine processEngine = Configuration.getProcessEngine(); TaskService taskService = processEngine.getTaskService(); String taskId = request.getParameter("id"); Task task = taskService.getTask(taskId);
//这里获取到task对象之后可以使用getVariable()方法获得task中保存的变量。
<legend>经理审核</legend> <form action="submit_manager.jsp" method="post"> <input type="hidden" name="taskId" value="${param.id}"> 申请人:<%=taskService.getVariable(taskId, "owner") %><br/> 请假时间:<%=taskService.getVariable(taskId, "day") %><br/> 请假原因:<%=taskService.getVariable(taskId, "reason") %><br/> <input name="result" type="submit" value="批准"/><input name="result" type="submit" value="驳回"/>
2、完成任务,经理点击批准的代码
//这里只要把当前任务节点需要的参数都放进map里面传递给task就可以。
ProcessEngine processEngine = Configuration.getProcessEngine(); TaskService taskService = processEngine.getTaskService(); String taskId = request.getParameter("taskId"); String result = request.getParameter("result"); result = new String(result.getBytes("ISO-8859-1"), "UTF-8"); taskService.completeTask(taskId, result);
这篇博客不想在继续了,因为今天和经理汇报了调研jbpm4的结果后,感觉不是很满意,bug很多,我简单列举几个:
现有的流程绘制查询gpdbug很多(不包括gbk的项目),乱码问题和编辑玩可视化界面 source界面代码重新生成的问题。
不是生成一些代码,很多重复性代码都需要收工来写,
结合现有项目的用户系统很不方便,
已经停止更新了,很多包会和先有项目的包有版本冲突
流程定义多样化不够完善。
毕竟是一个夭折的项目,夭折可能不合适,更像一个中途改嫁的妇人。。
开始研究jbpm5,我的资源里有下载jbpm4的小例子:上半部压缩包,下半部压缩包