jBPM Developers Guide(jBPM开发指南)--Chapter 3. BPMN 2.0(第六部分)

3.9. Complete example (including console task forms)( 完整示例(包括控制台任务表单))

 

    Prerequisites: to run the example, we assume that a working jBPM console has been installed on your JBoss server. If not, please run the 'demo.setup.jboss' install script first.

 

    前提条件:为了运行该示例,我们假设你已经在JBoss server中安装了jBPM控制台。如果没有,请先执行'demo.setup.jboss'安装脚本。

 

    The business process we're implementing looks as follows:

    我们实现的业务流程如下:



   You might recognize this example, since we’ve also implemented it in JPDL as an example in our distribution.

 

    你可能已经看过这个例子了,因为我们也在发布包中的示例中使用jPDL实现过它了。

 

    The business process is simple: an employee can start a new process and make a request for a certain amount of vacation days. After the request task has been completed, the manager will find a verification task in its tasklist. The Manager can now decide to accept or reject this request. Depending on the outcome (that’s the little rhombus on the outgoing sequence flow - it means there is a conditional expression on the sequence flow), a rejection message is send or the process ends. Do note that in fact we've used a shortcut here: instead of putting expressions on the outgoing sequence flow of the 'verify request' task, we've could have used an exclusive gateway after the user task to control the flow through the process. Also note that since we haven't implemented swimlanes yet (probably the next release), it's difficult to actually see who does what in the business process.

 

    业务流程很简单:一个员工可以启动一个新流程,申请一定时间的假期。在请求任务完成之后,经理会在任务列表中看到该审核任务。经理可以决定批准或驳回这个申请。根据outcome(那是外出顺序流上的小菱形 - 这意味着在顺序流上有条件表达式),会发送一个驳回信息或者流程结束。注意,实际上我们也可以不在'verify request'任务的外出顺序流上设置表达式,而是在用户任务之后使用一个唯一网关来控制流程的流向。也要注意,因为我们还没有实现泳道(可能在下一个版本会实现),所以很难看到谁在业务流程中。

 

    The XML version of this process looks as follows:

 

    流程的XML版本看起来像下面这样:

 

<process id="vacationRequestProcess" name="BPMN2 Example process using task forms">

    <startEvent id="start" />

    <sequenceFlow id="flow1" name="fromStartToRequestVacation"
      sourceRef="start" targetRef="requestVacation" />

    <userTask id="requestVacation" name="Request Vacation"
      implementation="other">
     <potentialOwner resourceRef="user" jbpm:type="group">
        <resourceAssignmentExpression>
          <formalExpression>user</formalExpression>
        </resourceAssignmentExpression>
      </potentialOwner>
      <rendering id="requestForm">
        <jbpm:form>org/jbpm/examples/bpmn/usertask/taskform/request_vacation.ftl</jbpm:form>
      </rendering>
    </userTask>

    <sequenceFlow id="flow2"
      name="fromRequestVacationToVerifyRequest" sourceRef="requestVacation"
      targetRef="verifyRequest" />

    <userTask id="verifyRequest" name="Verify Request"
      implementation="other">
      <potentialOwner resourceRef="user" jbpm:type="group">
        <resourceAssignmentExpression>
          <formalExpression>manager</formalExpression>
        </resourceAssignmentExpression>
      </potentialOwner>
      <rendering id="verifyForm">
        <jbpm:form>org/jbpm/examples/bpmn/usertask/taskform/verify_request.ftl</jbpm:form>
      </rendering>
    </userTask>

    <sequenceFlow id="flow3" name="fromVerifyRequestToEnd"
      sourceRef="verifyRequest" targetRef="theEnd">
      <conditionExpression xsi:type="tFormalExpression">
        ${verificationResult == 'OK'}
      </conditionExpression>
    </sequenceFlow>

    <sequenceFlow id="flow4"
      name="fromVerifyRequestToSendRejectionMessage" sourceRef="verifyRequest"
      targetRef="sendRejectionMessage">
      <conditionExpression xsi:type="tFormalExpression">
        ${verificationResult == 'Not OK'}
      </conditionExpression>
    </sequenceFlow>

    <scriptTask id="sendRejectionMessage" name="Send rejection Message"
      scriptLanguage="bsh">
      <script>
        <![CDATA[System.out.println("Vacation request refused!");]]>
      </script>
    </scriptTask>

    <sequenceFlow id="flow5"
      name="fromSendRejectionMessageToEnd" sourceRef="sendRejectionMessage"
      targetRef="theEnd" />

    <endEvent id="theEnd" name="End" />
</process>
    Note: this example is already installed when you've used the demo setup. Also note that we're using a Script Task here, to quickly write something as output instead of sending a real message (the diagram is showing a Service Task). Also note that we've taken some shortcuts here regarding task assignment (will be fixed in the next release).

 

    注意:当你在安装demo时该示例也就已经安装了。也要注意,我们这里使用了脚本任务(图形显示中的service task),为了快速体验,我们采用了控制台输出,而不是真正的发送信息。也要注意,我们这里在任务分配中也做了一些简化(会在下一个版本进行修复)。

 

    The constructs used in this implementation are all covered in the previous section. Also note that we're using the taskform functionality here, which is a custom jBPM extension for the rendering element of a User task.

 

    在这个示例中的结构覆盖了之前章节中的所有内容。也要注意我们这里使用了一个任务表单功能,这是jBPM一个自定义扩展,可以为用户任务渲染元素。

 

<userTask id="verifyRequest" name="Verify Request"
       implementation="other">
  <potentialOwner resourceRef="user" jbpm:type="group">
    <resourceAssignmentExpression>
      <formalExpression>user</formalExpression>
    </resourceAssignmentExpression>
  </potentialOwner>
  <rendering id="verifyForm">
    <jbpm:form>org/jbpm/examples/bpmn/usertask/taskform/verify_request.ftl</jbpm:form>
  </rendering>
</userTask>
     The mechanism regarding task forms for BPMN 2.0 is complete equivalent to that of JPDL. The form itself is a Freemarker template file that needs to be incorporated in the deployment. For example, the 'verify_request.ftl' form looks like as follows.

 

    BPMN 2.0里任务表单的机制与jPDL里完全一样。表单自身是一个Freemarker模板文件,需要放在发布中。比如,'verify_request.ftl'表单看起来像下面这样:

<html>
  <body>

    <form action="${form.action}" method="POST" enctype="multipart/form-data">
    
      <h3>Your employee, ${employee_name} would like to go on vacation</h3>
      Number of days: ${number_of_days}<br/>
      
      <hr>
      
      In case you reject, please provide a reason:<br/>
      <input type="textarea" name="reason"/><br/>
     
      <input type="submit" name="verificationResult" value="OK">
      <input type="submit" name="verificationResult" value="Not OK">
      
    </form>
  </body>
</html>
     Note that process variables can be accessed using the ${my_process_variable} construct. Also note that named input controls (eg. input field, submit button) can be used to define new process variables. For example, the text input of the following field will be stored as the process variable 'reason'

 

    注意,流程变量可以使用 ${my_process_variable}来访问也要注意对输入控件进行命名(比如,文本输入框,提交按钮),名称用来 定义新流程变量 比如,下面的文本输入会被保存为流程变量'reason'

<input type="textarea" name="reason"/>
     Note that there are two submit buttons (which makes sense if you look at the 'OK' and 'Not OK' sequence flows going out the 'request vacation' task. By pressing one of these buttons, the process variable 'verificationResult' will be stored. It can then be used to evaluate the outgoing sequence flow:

 

    注意这里有两个提交按钮(这是当然的,因为'request vacation'任务里有两个外出顺序流'OK''Not OK')。通过点击其中一个按钮,流程变量'verificationResult'会被保存起来。它可以用来执行外出的顺序流:

<sequenceFlow id="flow3" name="fromVerifyRequestToEnd"
      sourceRef="verifyRequest" targetRef="theEnd">
  <conditionExpression xsi:type="tFormalExpression">
    ${verificationResult == 'OK'}
  </conditionExpression>
</sequenceFlow>
     The process can now be deployed. You can use the ant deploy task for this (see examples), or you can point your jBPM configuration to the database of the console. To deploy your process programmatically, you need to add the task forms to your deployment:

 

    流程现在可以发布了。你可以使用ant的发布任务来做这些事情(参考示例),或者你可以指定你的jBPM配置到控制台的数据库。为了用编程的方式发布你的流程,你需要把任务表单添加到你的发布中:

NewDeployment deployment = repositoryService.createDeployment();
deployment.addResourceFromClasspath("org/jbpm/examples/bpmn/usertask/taskform/vacationrequest.bpmn.xml");
deployment.addResourceFromClasspath("org/jbpm/examples/bpmn/usertask/taskform/request_vacation.ftl");
deployment.addResourceFromClasspath("org/jbpm/examples/bpmn/usertask/taskform/verify_request.ftl");
deployment.deploy();
     You can now embed (or run on a standalone server) this business process, by using the familiar jBPM API operations. For example, process instances can now be started using the key (ie. the process id for BPMN 2.0):

 

    通过调用熟悉的jBPM API操作你现在可以嵌入(或在单独的服务器中)这个业务流程。比如,流程实例现在可以使用 key来启动(比如,BPMN 2.0的流程id):

ProcessInstance pi = executionService.startProcessInstanceByKey("vacationRequestProcess");
     Or tasks list can be retrieved:

 

    任务列表可以这样获得:

Task requestTasktask = taskService.createTaskQuery().candidate("peter").uniqueResult();
     When deploying to the jBPM console database, you should see our new business process popping up.

 

    当在jBPM控制器数据库部署后,你应该看到我们的新业务流程了。



   After you start a new process, a new task should be available in the employee's tasklist. When clicking on 'view', the task form will be displayed, requesting to fill in some variables for further use in the process.

 

    在你启动一个新流程后,一个新任务应该在员工的任务列表中了。 当点击'view'以后,任务表单会被显示出来, 在这里填写了会在流程中使用的变量。



    After task completion, the manager will find a new verification task in his task list. He can now accept or reject the vacation request, based on the input of the employee.

 

    在任务结束之后,经理会在他的任务列表中看到新的审核任务。他现在可以基于员工的输入同意或驳回该请假申请。



    Since the database schema remains unchanged when we added BPMN 2.0 on top of the jBPM PVM, all existing reports can be applied to our new BPMN 2.0 processes.

 

    因为数据库表结构没有变化,我们只是在jBPM PVM上面添加了BPMN 2.0,所以所有已存的报表都可以用于我们的新BPMN 2.0流程中。