jBPM(十):webSale的"页面流"介绍

        通过前面几篇博客,我们看到了jBPM自带例子webSale可以在Tomcat+Mysql的环境中运行了. 这也是我研究jBPM的第一步. 希望对jBPM有个目无全牛地了解/理解/掌握,这里有必要介绍下这个webSale例子, 毕竟它是通往"全牛"的引子, 同时也可以作为项目中调用jBPM的一个不错practice.
    这里采用"页面流" 方式(也就是顺着页面的跳转)来展开对webSale的介绍,及其背后调用的jBPM的相关API.另由于这个webSale是用JSF来作显示的,对JSF不熟悉的看官可找些文档看下,以下的介绍中不会再做JSF方面的介绍.

     第一步, 进入登录界面.  这时页面上以下拉菜单方式给出webSale支持的用户名, 这些用户名也正是流程中task的执行者. 那这些用户名是如何获得的? UserBean的getUsers方法里, 执行了这样调用:
        new IdentitySession(JbpmContext.getCurrentJbpmContext().getSession()).getUsers(). // 注,为了行文方便,我这里更紧凑地改写了原代码, 以下同.

    第二步, 选一个用户后, 点"Log In"按钮时, 对应的login方法是, 执行JbpmContext.getCurrentJbpmContext().setActorId(userName)设置actor. 跳转到home页面(对应着home.jsp文件).
        在home页面中, webSale做了两件事: 显示当前登录用户负责的Tasklist, 显示已经发布的流程. 下面看这些数据库是怎么来的.
        显示当前登录用户负责的Tasklist时, 背后执行了taskMgmtSession.findTaskInstances(currentUserName)语句, 这个返回一个装有TaskInstance的list, 再在页面上遍历list以 "taskInstance.taskMgmtInstance.taskMgmtDefinition.processDefinition.name/version" 方式取出流程定义中的name和version信息, 并给每一个taskInstance的Name加了一个执行链接调用homeBean中的selectTaskInstance方法.
        显示已经发布的流程时, 背后执行graphSession.findLatestProcessDefinitions(), 在JSP页面里, 以processDefinition.taskMgmtDefinition.startTask.name方式获得流程的首任务名,并给些任务名加链 接去执行homeBean的startProcessInstance方法.
 
    第三步, 在上一步返回的home页面中, 点任务名链接, 调用startProcessInstance方法来启动流程处理. 此方法中先执行"new ProcessInstance(graphSession.loadProcessDefinition(processDefinitionId)). getTaskMgmtInstance().createStartTaskInstance()"来启动流程, 再通过"jbpmContext.save(processInstance)"保存上面new出来的processInstance. 调用taskBean中的initialize(taskInstance)处理前面createStartTaskInstance方法返回的 taskInstance为下一页面的显示做准备. 跳转到task页面.

    第四步, task页面中展现数据/流程定义图片.
        先说这里简单的(调用简单,但背后的实现还是挺复杂的)图片展现: <jbpm:processimage task="${taskBean.taskInstanceId}"/>.

        接着看数据显示, 其实这一块的工作都是在上面taskBean中的initialize(taskInstance)方法做好的. 那这个方法又做了些什么呢? 两件事: 显示跟当前taskInstance绑定的variable信息及当前taskInstance的transition(也就是针对当前 taskInstance都有什么样的控制).  
        variable信息这样得到: taskInstance.getTask().getTaskController().getVariableAccesses(){variableAccess | variableAccess .getMappedName  ==> mappedName, taskInstance.getVariable(getMappedName) => value, new TaskFormParameter(variableAccess, value)}. 好像是用了类似于python/groovy/ruby那样的可执行的伪代码. 这些可执行的伪代码也打开了设计新编程语言的可能性.
        当前taskInstance的transition又是这样得到: taskInstance.getAvailableTransitions.

    第五步, 在上一步的基础上, 从本质上来看,填写必要信息后有两种操作:保存当前信息并不结束当前taskInstance, 保存当前信息并结束当前taskInstance使流程进入下一taskInstance. 这两个操作分别对应着两个方法save和saveAndClose-- 这个saveAndClose方法中有调用save方法.
        
        先看save方法,它做了两件事: "taskFormParameter.isWritable && taskFormParameter.getValue  ==> taskInstance.setVariable(taskFormParameter.getLabel(), taskFormParameter.getValue())" 更新taskInstance中相应的variable信息; jbpmContext.save(taskInstance).

        saveAndClose方法中三件事: 调用taskInstance.end结束当前taskInstance; processInstance.getLoggingInstance().getLogs(TaskAssignLog.class){ | getTaskNewActorId}显示下一taskInstance的负责人; jbpmContext.save(taskInstance).

    至此, 我们采用第二步返回页面中的startProcessInstance走了一遍, 若采用selectTaskInstance的话,"页面流" 会直接跳到第四步中的task页面, 就不再另行介绍.
--------------------------------
   快要写完本博客了, 有些感悟:
        0, 为什么要整理这么个文字版的webSale描述呢? 一是为了把现在的记忆以文字形式保存下来, 以后查看时不必再去看webSale中JSP到JavaBean的跳转. 更重要的是为了后续博客的引用, 也即当要描述一个jBPM API时不必再介绍它的应用场景,直接给出这里是第几步即可.
        1, 上面这些描述用时序图来表达会简洁明了的多.
        2, 体会到像Python那样的可执行伪代码的好处: 直接用Python这样的动态语言来"写"文档.

你可能感兴趣的:(jsp,python,JSF,jbpm,groovy)