- 浏览: 4180 次
- 性别:
- 来自: 无锡
最新评论
-
fanl1982:
同求代码,谢谢,19680460@qq.com
JBPM4得到所有已经完成节点的主数据类以及数据记录信息 -
sd1992585:
如丝袜般顺滑的写代码~~ 亮了
JBPM4得到所有已经完成节点的主数据类以及数据记录信息 -
yuzhousky:
你好,能将JBPM4.4获取的已经完成的结点的信息的代码发份不 ...
JBPM4得到所有已经完成节点的主数据类以及数据记录信息 -
hulefei29:
程序猿的路才刚刚开始
2011总结 -
pdd7531:
biucb 写道一年时间熟悉了这么多技术啊,光Oracle千万 ...
2011总结
公司产品一直用JBPM作为流程驱动核心,之前的主要应用场景为数据审批等变动较小的业务范围,今年新开发了产品模块,用JBPM来驱动协同项目,实现多人协同工作的需求,在WBS分解项目时无法做到确保项目运行过程中不会变动,所以出现了项目运行过程中需要能动态改变流程定义并保证之前已经运行过的项目节点数据不会丢失的需求。
在网上搜索了很多,没有发现类似的流程实例拷贝的功能,自己试着实现了一个版本,当然有诸多限制,譬如已完成节点不可编辑,不可删除,否则流程无法正确流至上个流程实例的当前节点。
数据库中增加了流程过程描述表,主要字段为主流程实例ID,项目ID,流程任务ID,项目任务ID,以及任务的outCome。流程运行过程中,完成任务操作时往这张表中增加记录,记录流程运行过程。
实例拷贝主要分为六步,一、根据项目ID获取最新流程定义。二、根据最新流程定义获取上个版本流程定义。三、根据上个版本流程定义获取上个版本的流程实例。四、根据上个版本流程实例抽取出上个版本中已经运行的任务的描述,包括任务关联数据,任务走向等。五、开始最新流程实例,递归寻找当前任务,从上个版本的任务描述中拷贝关联数据以及确定任务走向。六、清理上个版本流程数据。
实现的重点是要考虑分支,子流程等复杂元素,特变是嵌套分支,嵌套子流程等也要能完美运行通过,主要的业务是在抽取历史任务数据以及递归推动最新流程,绑定历史任务数据的地方。代码的编写过程中,也运用了一些JBMP的源码知识,譬如控制执行先后顺序参开了ExecutionImpl的performAtomicOperation的模式,匹配历史任务时采用了责任链模式,将历史任务按照执行顺序组织成责任链模式,匹配成功后跳过已匹配的任务。
附上关键代码:
在网上搜索了很多,没有发现类似的流程实例拷贝的功能,自己试着实现了一个版本,当然有诸多限制,譬如已完成节点不可编辑,不可删除,否则流程无法正确流至上个流程实例的当前节点。
数据库中增加了流程过程描述表,主要字段为主流程实例ID,项目ID,流程任务ID,项目任务ID,以及任务的outCome。流程运行过程中,完成任务操作时往这张表中增加记录,记录流程运行过程。
实例拷贝主要分为六步,一、根据项目ID获取最新流程定义。二、根据最新流程定义获取上个版本流程定义。三、根据上个版本流程定义获取上个版本的流程实例。四、根据上个版本流程实例抽取出上个版本中已经运行的任务的描述,包括任务关联数据,任务走向等。五、开始最新流程实例,递归寻找当前任务,从上个版本的任务描述中拷贝关联数据以及确定任务走向。六、清理上个版本流程数据。
实现的重点是要考虑分支,子流程等复杂元素,特变是嵌套分支,嵌套子流程等也要能完美运行通过,主要的业务是在抽取历史任务数据以及递归推动最新流程,绑定历史任务数据的地方。代码的编写过程中,也运用了一些JBMP的源码知识,譬如控制执行先后顺序参开了ExecutionImpl的performAtomicOperation的模式,匹配历史任务时采用了责任链模式,将历史任务按照执行顺序组织成责任链模式,匹配成功后跳过已匹配的任务。
附上关键代码:
public abstract class EDMAtomicOperation implements Serializable { //serialVersionUID is private static final long serialVersionUID = 1L; public static final EDMAtomicOperation GET_LATEST_PDID = new GetLatestPdIdOperation(); public static final EDMAtomicOperation GET_LAST_VERSION_PDID = new GetLastVersionPdIdOperation(); public static final EDMAtomicOperation GET_LAST_VERSION_PIID = new GetLastVersionPiIdOperation(); public static final EDMAtomicOperation GET_LAST_VERSION_TASKDESC = new GetLastVersionTaskDescOperation(); public static final EDMAtomicOperation COPY_PROCESS = new CopyProcessDataOperation(); public static final EDMAtomicOperation CLEAN_OLD_PROCESS = new CleanOldProcessOperation(); public abstract void perform(ProcessCourserImpl processCourse); }
public interface ProcessCourser { public void sign(); public String getErrorMessage(); }
public class ProcessCourserImpl implements ProcessCourser,Serializable{ //serialVersionUID is private static final long serialVersionUID = -3239018905632135241L; public ProcessCourserImpl(String projectId, ProcessCourseTool processCourseTool, String userShowName){ this.projectId = projectId; this.processCourseTool = processCourseTool; this.userShowName = userShowName; } /** *@Function Name: sign *@Description: 开始工作 *@Date Created: 2013-12-24 下午04:46:35 *@Author: Pan Duan Duan *@Last Modified: , Date Modified: */ @Override public void sign() { //如果还未获取最新流程定义 if("".equals(latestPdId)){ performAtomicOperation(EDMAtomicOperation.GET_LATEST_PDID); } } /** *@Function Name: performAtomicOperation *@Description: @param operation *@Date Created: 2013-12-25 上午08:34:54 *@Author: Pan Duan Duan 执行操作 *@Last Modified: , Date Modified: */ public synchronized void performAtomicOperation(EDMAtomicOperation operation) { performAtomicOperationSync(operation); } /** *@Function Name: performAtomicOperationSync *@Description: @param operation *@Date Created: 2013-12-25 上午08:35:02 *@Author: Pan Duan Duan 以同步的方式执行操作 *@Last Modified: , Date Modified: */ private void performAtomicOperationSync(EDMAtomicOperation operation) { //初始化 if (atomicOperations==null) { atomicOperations = new LinkedList<EDMAtomicOperation>(); atomicOperations.offer(operation); while (! atomicOperations.isEmpty()) { EDMAtomicOperation atomicOperation = atomicOperations.poll(); atomicOperation.perform(this); } }else { atomicOperations.offer(operation); } }
public class CopyProcessDataOperation extends EDMAtomicOperation { Logger log = Logger.getLogger(this.getClass().getName()); //serialVersionUID is private static final long serialVersionUID = -6126577335188267494L; @Override public void perform(ProcessCourserImpl processCourse) { log.warn("Copy Process Step 5: copy old process info to the new one"); //最新流程定义 String latestPdId = processCourse.getLatestPdId(); //得到当前用户显示名称 String userShowName = processCourse.getUserShowName(); String latestPiId = processCourse.getProcessCourseTool().getProcessInstanceTool().startProcessInstance(latestPdId,userShowName); //上个版本流程任务描述集合 List<EDMTaskDesc> lastTaskDescs = processCourse.getTaskDescs(); if(null != lastTaskDescs && lastTaskDescs.size() > 0){ processFlow(latestPiId,processCourse); } processCourse.performAtomicOperation(EDMAtomicOperation.CLEAN_OLD_PROCESS); } /** *@Function Name: processFlow *@Description: @param latestProcessInstance *@Description: @param processCourse *@Date Created: 2013-12-26 上午09:26:54 *@Author: Pan Duan Duan 驱动流程 复制数据 *@Last Modified: , Date Modified: */ private void processFlow(String latestPiId, ProcessCourserImpl processCourse) { //当前流程主流程ID String mainPiId = latestPiId; // ProcessInstanceTool processInstanceTool = processCourse.getProcessCourseTool().getProcessInstanceTool(); //当前任务集合 List<Task> currentTasks = new ArrayList<Task>(); while(currentTasks.isEmpty()){ //获取最新流程的当前任务集合 getNextTaskByPiId(mainPiId, currentTasks, processInstanceTool); //已完成任务集合 List<Task> completedTask = new ArrayList<Task>(); for(Task currentTask : currentTasks){ //完成任务 拷贝任务数据 boolean completed = complateCurrentTask(currentTask,processInstanceTool,processCourse,mainPiId); if(completed){ completedTask.add(currentTask); } } //移除已经完成的任务 推动流程 for(Task tempTask : completedTask){ currentTasks.remove(tempTask); } } // } /** *@param processCourse * @Function Name: complateCurrentTask *@Description: @param currentTask *@Description: @param processInstanceTool *@Date Created: 2013-12-26 上午11:05:06 *@Author: Pan Duan Duan 完成当前任务 *@Last Modified: , Date Modified: */ private boolean complateCurrentTask(Task currentTask, ProcessInstanceTool processInstanceTool, ProcessCourserImpl processCourse, String mainPiId) { //流程引擎 ProcessEngine processEngine = processInstanceTool.getProcessEngine(); //得到流程实例Service ExecutionService executionService = processEngine.getExecutionService(); //得到taskService TaskService taskService = processEngine.getTaskService(); //返回结果 boolean flag = false; // try{ //获取任务ID String taskId = currentTask.getId(); //得到executionId String executionId = currentTask.getExecutionId(); //得到流程实例 Execution execution = executionService.findExecutionById(executionId); //得到主线流程 execution = processInstanceTool.findMainExecution(execution); //获取项目任务ID String prjTaskId = processInstanceTool.getTaskDataIdByProcessTaskId(taskId); //复制任务数据 EDMTaskDesc copyedTaskDesc = processCourse.getTaskDescs().get(0).doCopy(prjTaskId, processInstanceTool); //获取新的变量ID if(null != copyedTaskDesc){ String newVariableId = copyedTaskDesc.getNewVariableId(); //获取新变量实例 EdmTaskVariable edmTaskVariable = processInstanceTool.getEdmTaskVariableById(newVariableId); //获取任务执行人 String taskOperator = edmTaskVariable.getOperator(); //转化为登录名称 taskOperator = processInstanceTool.getUserLoginNameByShowName(taskOperator); //注入流程任务中 processEngine.execute(new TaskDelegateCmd(taskId, taskOperator)); //保存任务变量 executionService.createVariable(execution.getId(), taskId, edmTaskVariable, true); //得到任务流向 String outCome = copyedTaskDesc.getOutCome(); //完成任务 taskService.completeTask(taskId,outCome); //保存执行过程 processCourse.getProcessCourseTool().saveTaskCourse(mainPiId, processCourse.getProjectId(), taskId, copyedTaskDesc.getPrjTaskId(), outCome); //修改任务状态 processCourse.getProcessCourseTool().changePrjTaskState(copyedTaskDesc.getPrjTaskId(), ProjectState.STATE_COMPLETED); flag = true; } }catch (Exception e) { e.printStackTrace(); } return flag; } /** *@Function Name: getNextTaskByPiId *@Description: @param hisPiId *@Description: @param processEngine *@Description: @return 得到下一个任务 *@Date Created: 2013-7-24 下午02:48:15 *@Author: Pan Duan Duan *@Last Modified: , Date Modified: */ public void getNextTaskByPiId(String mainPiId, List<Task> tasks, ProcessInstanceTool processInstanceTool) { ProcessEngine processEngine = processInstanceTool.getProcessEngine(); //任务Serveice TaskService taskService = processEngine.getTaskService(); //流程实例Service ExecutionService executionService = processEngine.getExecutionService(); //HistoryService HistoryService historyService = processEngine.getHistoryService(); RepositoryService repositoryService = processEngine.getRepositoryService(); //得到流程实例 Execution excution = executionService.findExecutionById(mainPiId); //寻找主流程当前任务 List<Task> taskList = taskService.createTaskQuery().processInstanceId(mainPiId).list(); if(null != taskList && taskList.size() > 0) { tasks.addAll(taskList); } //尋找 分支 当前任务 Collection<? extends Execution> executions = excution.getExecutions(); if(executions.size() > 0) { for(Execution branchExecution : executions){ getNextTaskByPiId(branchExecution.getId(), tasks, processInstanceTool); } } //寻找子流程 String subExecutionId = null; ExecutionImpl executionImpl = (ExecutionImpl) excution; //得到activityName String activityName = executionImpl.getActivityName(); if(null != activityName){ //获取主线流程 String mainBranchExecutionId = processInstanceTool.getProcessInstanceService().getMainPiIdByBranchPiId(excution.getId()); //根据当前流程 得到所有父子流程集合 List<Map<String,Object>> processInfos = processInstanceTool.getProcessInstanceIds(mainBranchExecutionId); for(Map<String,Object> processInfo : processInfos){ String piId = CommonTools.Obj2String(processInfo.get("PIID")); //得到流程实例 HistoryProcessInstance hisPi = historyService.createHistoryProcessInstanceQuery().processInstanceId(piId).uniqueResult(); if(null != hisPi){ //得到流程定义 ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().processDefinitionId(hisPi.getProcessDefinitionId()).uniqueResult(); //得到流程定义名称 String pdName = pd.getName(); //得到流程定义 if(activityName.equals(pdName)){ subExecutionId = piId; break; } } } if(null != subExecutionId){ getNextTaskByPiId(subExecutionId, tasks, processInstanceTool); } } } }
public class GetLastVersionTaskDescOperation extends EDMAtomicOperation{ Logger log = Logger.getLogger(this.getClass().getName()); //serialVersionUID is private static final long serialVersionUID = 1665471796593388193L; @Override public void perform(ProcessCourserImpl processCourse) { log.warn("Copy Process Step 4: get the last version flow task description"); //获取上个版本的 流程实例ID String lastVersionPiId = processCourse.getLastVersionPiId(); if(!"".equals(lastVersionPiId)){ List<EDMTaskDesc> taskDescs = getLastVersionTaskDesc(lastVersionPiId,processCourse); //组织责任链 organizeTaskChain(taskDescs); processCourse.setTaskDescs(taskDescs); } processCourse.performAtomicOperation(EDMAtomicOperation.COPY_PROCESS); } /** *@Function Name: organizeTaskChain *@Description: @param taskDesc *@Date Created: 2013-12-26 上午10:23:30 *@Author: Pan Duan Duan 组织责任链 *@Last Modified: , Date Modified: */ private void organizeTaskChain(List<EDMTaskDesc> taskDescs) { int taskDescSize = taskDescs.size(); if(taskDescSize > 0){ //临时变量 EDMTaskDesc tempTaskDesc = taskDescs.get(taskDescSize - 1); //遍历循环 for(int index = taskDescSize - 2; index >= 0; index--){ EDMTaskDesc taskDesc = taskDescs.get(index); taskDesc.setNextEDMTaskDesc(tempTaskDesc); tempTaskDesc = taskDesc; } } } /** *@Function Name: getLastVersionTaskDesc *@Description: @param lastVersionPiId *@Description: @param processCourse *@Description: @return 获取上个版本的任务描述 *@Date Created: 2013-12-25 上午11:27:22 *@Author: Pan Duan Duan *@Last Modified: , Date Modified: */ private List<EDMTaskDesc> getLastVersionTaskDesc( String lastVersionPiId, ProcessCourserImpl processCourse) { List<EDMTaskDesc> retVal = new ArrayList<EDMTaskDesc>(); ProcessInstanceTool processInstanceTool = processCourse.getProcessCourseTool().getProcessInstanceTool(); ProcessEngine processEngine = processInstanceTool.getProcessEngine(); //获取流程历史服务 HistoryService historyService = processEngine.getHistoryService(); //获取父子流程集合 List<Map<String, Object>> processIdDescs = processCourse.getProcessCourseTool().getProcessInstanceTool().getProcessInstanceService().getProcessInstanceIds(lastVersionPiId); //遍历获取已完成任务集合 Set<String> processInstanceIds = new HashSet<String>(); //加入主流程 processInstanceIds.add(lastVersionPiId); for(Map<String, Object> processDescMap : processIdDescs){ //得到流程ID String piId = CommonTools.Obj2String(processDescMap.get("PIID")); processInstanceIds.add(piId); } for(String piId : processInstanceIds){ //得到历史流程 HistoryProcessInstance historyProcessInstance = historyService.createHistoryProcessInstanceQuery().processInstanceId(piId).uniqueResult(); //得到历史流程定义 String hisPdId = historyProcessInstance.getProcessDefinitionId(); //获取任务表单描述 XmlFormReader formReader = processEngine.execute(new GetFormReaderCommand(hisPdId)); List<HistoryActivityInstance> historyActivityInstances = historyService.createHistoryActivityInstanceQuery().processInstanceId(piId).list();; //遍历任务集合 for(HistoryActivityInstance hisAci : historyActivityInstances){ //过滤掉正在进行的 以及非正常任务节点 if(hisAci.getEndTime() == null || ((HistoryActivityInstanceImpl)hisAci).getType().equals("sub-process")){ continue; } //强转为实现类 HistoryActivityInstanceImpl hisAcImpl = (HistoryActivityInstanceImpl) hisAci; XmlForm xmlForm = formReader.getFormByName(hisAcImpl.getActivityName()); //获取历史任务ID String taskId = processInstanceTool.getTaskIdByHaiImplId(String.valueOf(hisAcImpl.getDbid())); //获取历史变量值 String hisVariId = CommonTools.Obj2String(historyService.getVariable(piId, taskId)); //存储 EDMTaskDesc edmTaskDesc = new EDMTaskDesc(); edmTaskDesc.setHisTaskId(taskId); edmTaskDesc.setVariableId(hisVariId); edmTaskDesc.setPrjTaskId(xmlForm == null ? "" : xmlForm.getId()); retVal.add(edmTaskDesc); } } //增加outCome并排序 retVal = appendOutCome(retVal,processCourse); return retVal; } /** *@Function Name: appendOutCome *@Description: @param retVal *@Description: @return 增加任务流向 以及 排序 *@Date Created: 2013-12-26 上午08:23:06 *@Author: Pan Duan Duan *@Last Modified: , Date Modified: */ /** *@param processCourse * @Function Name: appendOutCome *@Description: @param source *@Description: @return *@Date Created: 2013-12-26 上午08:27:16 *@Author: Pan Duan Duan *@Last Modified: , Date Modified: */ private List<EDMTaskDesc> appendOutCome(List<EDMTaskDesc> source, ProcessCourserImpl processCourse) { //返回结果 List<EDMTaskDesc> desc = new ArrayList<EDMTaskDesc>(); //获取流程执行过程 StringBuffer querySql = new StringBuffer(); querySql.append("SELECT ID,MAIN_PIID,PROJECT_ID,FLOW_TASK_ID,PRJ_TASK_ID,OUTCOME FROM "); querySql.append("JBPM4_EDM_COURSE WHERE MAIN_PIID = ? AND PROJECT_ID = ? ORDER BY ID"); //获取查询结果 List<Map<String,Object>> queryList = processCourse.getProcessCourseTool().getProcessInstanceTool().getMetaDaoFactory().getJdbcTemplate(). queryForList(querySql.toString(),new Object[]{processCourse.getLastVersionPiId(),processCourse.getProjectId()}); //遍历组织 for(Map<String,Object> dataMap : queryList){ //流程任务ID String flowTaskId = CommonTools.Obj2String(dataMap.get("FLOW_TASK_ID")); //任务流向 String outCome = CommonTools.Obj2String(dataMap.get("OUTCOME")); //从sources中寻找 for(EDMTaskDesc tempTaskDesc : source){ if(flowTaskId.equals(tempTaskDesc.getHisTaskId())){ tempTaskDesc.setOutCome(outCome); desc.add(tempTaskDesc); break; } } } return desc; }
相关推荐
JBPM流程监控的实现过程
JBPM采购申请系统——08_JBPM流程节点.7z JBPM采购申请系统——08_JBPM流程节点.7z JBPM采购申请系统——08_JBPM流程节点.7z JBPM采购申请系统——08_JBPM流程节点.7z JBPM采购申请系统——08_JBPM流程节点.7z JBPM...
jbpm流程监控的实现
JBPM是JBOSS公司的一个开源工作流产品,它功能强大,商业工作流所提供的功能它基本上都有。然而在JBPM中没有提供流程监控的功能的相关API,这点让很多使用JBPM做企业应用的开发人员颇为头疼。
jbpm流程引擎内核还提供了许多其他的功能,例如事件处理、组织适配、时间调度、消息服务等。 了解jbpm流程引擎内核的设计思想和结构,需要具备一定的工作流基本概念,例如流程系统结构、流程定义和流程实例等。同时...
JBPM流程引擎设计 工作流资料JBPM流程引擎设计 工作流资料JBPM流程引擎设计 工作流资料JBPM流程引擎设计 工作流资料JBPM流程引擎设计 工作流资料
文档详细介绍了如何利用JBPM开发流程应用,从框架构造到节点处理。
jbpm流程引擎框架源码,一套流行的流程引擎框架代码
JBPM流程代码演示
jbpm4.4流程图
jbpm流程
jbpm流程设计器,适用于jbpm工作流设计
eclipse3.4解压版带jbpm流程定义插件,很简单,只需解压即可使用
讲讲jbpm流程引擎内核.很好的教程,从别人那下的,贡献给大家!
jbpm工作流程jbpm工作流程jbpm工作流程jbpm工作流程jbpm工作流程
jbpm流程设计器 + 生成对应xml文档: 内部含有: jbpm控件 1: myflow2:插件原本内容 访问地址:http://localhost:8080/jbpmFlow1/myflow2/demo4.jsp 实现生成对应xml文档 并写有对xml文档读取存储到对象中,...
关于jbpm 的详细介绍,有关jbpm的功能、流程图、以及特殊功能。少有的资源
jbpm业务流程设计demo 基于jbpm设计的业务流程
JBPM Web流程设计器,用js+extjs画的jbpm流程设计器,与eclipse插件类似,可以进行自定义。
通过查看JBPM的表,我们知道要实现流程监控功能就是把JBPM当中的JBPM_PROCESSDEFINITION(已发布的流程表),JBPM_PROCESSINSTANCE(流程实例表),JBPM_TASKINSTANCE(流程产生的任务实例表)这三张表串联起来就可以...