Drools 5.1.1_DOC (58)

Drools 5.1.1_DOC_Drools Flow
 

第14章 业务流程模型与表示法( Business Process Model and Notation——BPMN 2.0)

 
业务流程模型与表示法 (BPMN) 2.0规范正稳步向前成为一个伟大的标准,我们采用它在Drools流中建模。BPMN 2.0不仅就如何图形化表示一个业务流程(如BPMN 1)定义了一个标准,而且现在包括了用于元素定义的执行语义,以及有关如何存储(与共享)流程定义的一种XML格式。

Drools 流允许你执行用BPMN 2.0 XML格式定义的流程,正如它允许你执行用自定义规则流(RuleFlow)格式的流程一样的方式。这意味着你可以使用相同的API,引擎和组 件,如Guvnor和 gwt-console, 来执行和管理你的BPMN 2.0流程。

 

除了我们已经支持的非常重要的子集——包括所有通用节点类型外,我们还实现了所有定义在BPMN 2.0规范中的节点类型和属性。以下列表给出了已可以使用 BPMN 2.0 XML格式执行的各种元素的一个概述:

 

  • Flow objects
    • Events
      • Start Event (None, Conditional, Signal, Message, Timer)
      • End Event (None, Terminate, Error, Escalation, Signal, Message, Compensation)
      • Intermediate Catch Event (Signal, Timer, Conditional, Message)
      • Intermediate Throw Event (None, Signal, Escalation, Message, Compensation)
      • Non-interrupting Boundary Event (Escalation, Timer)
      • Interrupting Boundary Event (Escalation, Error, Timer, Compensation)
    • Activities
      • Script Task (Java or MVEL expression language)
      • Task
      • Service Task
      • User Task
      • Business Rule Task
      • Manual Task
      • Send Task
      • Receive Task
      • Reusable Sub-Process (Call Activity)
      • Embedded Sub-Process
      • Ad-Hoc Sub-Process
      • Data-Object
    • Gateways
      • Diverging
        • Exclusive (Java, MVEL or XPath expression language)
        • Inclusive (Java, MVEL or XPath expression language)
        • Parallel
        • Event-Based
      • Converging
        • Exclusive
        • Parallel
    • Lanes
  • Data
    • Java type language
    • Process properties
    • Embedded Sub-Process properties
    • Activity properties
  • Connecting objects
    • Sequence flow

 

例如,思考以下执行评估的BPMN流程。每当一个评估流程为一个特定雇员启动时,该雇员必须首先执行一个自我评估,然后才是那个项目管理员的,并且人力资源管理员也必须填写它们的评估,如下图所示 。

 

 

 

这个流程的一个可执行版本,使用BPMN 2.0 XML表达,看起来像这样(注意,该流程需要包含所有使它执行的细节,包括每个出现任务的所有参数,因此是一个大型流程定义):

 

<?xml version="1.0" encoding="UTF-8"?> 
<definitions id="Definition"
             targetNamespace="http://www.jboss.org/drools"
             typeLanguage="http://www.java.com/javaTypes"
             expressionLanguage="http://www.mvel.org/2.0"
             xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
             xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
             xs:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd"
             xmlns:g="http://www.jboss.org/drools/flow/gpd"
             xmlns:tns="http://www.jboss.org/drools">

  <process processType="Private" isExecutable="true" id="com.sample.evaluation" name="Evaluation Process" >

    <!-- process variables -->
    <property id="employee" itemSubjectRef="_employeeItem"/>

    <!-- nodes -->
    <startEvent id="_1" name="StartProcess" g:x="16" g:y="56" g:width="48" g:height="48" />
    <userTask id="_2" name="Self Evaluation" g:x="96" g:y="56" g:width="143" g:height="48" >
      <ioSpecification>
        <dataInput id="_2_CommentInput" name="Comment" />
        <dataInput id="_2_SkippableInput" name="Skippable" />
        <dataInput id="_2_TaskNameInput" name="TaskName" />
        <dataInput id="_2_ContentInput" name="Content" />
        <dataInput id="_2_PriorityInput" name="Priority" />
        <inputSet>
          <dataInputRefs>_2_CommentInput</dataInputRefs>
          <dataInputRefs>_2_SkippableInput</dataInputRefs>
          <dataInputRefs>_2_TaskNameInput</dataInputRefs>
          <dataInputRefs>_2_ContentInput</dataInputRefs>
          <dataInputRefs>_2_PriorityInput</dataInputRefs>
        </inputSet>
        <outputSet>
        </outputSet>
      </ioSpecification>
      <dataInputAssociation>
        <targetRef>_2_CommentInput</targetRef>
        <assignment>
          <from xs:type="tFormalExpression">You need to perform a self-evaluation</from>
          <to xs:type="tFormalExpression">_2_CommentInput</to>
        </assignment>
      </dataInputAssociation>
      <dataInputAssociation>
        <targetRef>_2_SkippableInput</targetRef>
        <assignment>
          <from xs:type="tFormalExpression">false</from>
          <to xs:type="tFormalExpression">_2_SkippableInput</to>
        </assignment>
      </dataInputAssociation>
      <dataInputAssociation>
        <targetRef>_2_TaskNameInput</targetRef>
        <assignment>
          <from xs:type="tFormalExpression">Performance Evaluation</from>
          <to xs:type="tFormalExpression">_2_TaskNameInput</to>
        </assignment>
      </dataInputAssociation>
      <dataInputAssociation>
        <targetRef>_2_ContentInput</targetRef>
        <assignment>
          <from xs:type="tFormalExpression"></from>
          <to xs:type="tFormalExpression">_2_ContentInput</to>
        </assignment>
      </dataInputAssociation>
      <dataInputAssociation>
        <targetRef>_2_PriorityInput</targetRef>
        <assignment>
          <from xs:type="tFormalExpression">1</from>
          <to xs:type="tFormalExpression">_2_PriorityInput</to>
        </assignment>
      </dataInputAssociation>
      <potentialOwner>
        <resourceAssignmentExpression>
          <formalExpression>#{employee}</formalExpression>
        </resourceAssignmentExpression>
      </potentialOwner>
    </userTask>
    <parallelGateway id="_3" name="Diverge" g:x="271" g:y="56" g:width="49" g:height="49" gatewayDirection="Diverging" />
    <userTask id="_4" name="HR Manager Evaluation" g:x="352" g:y="96" g:width="225" g:height="48" >
      <ioSpecification>
        <dataInput id="_4_CommentInput" name="Comment" />
        <dataInput id="_4_SkippableInput" name="Skippable" />
        <dataInput id="_4_TaskNameInput" name="TaskName" />
        <dataInput id="_4_ContentInput" name="Content" />
        <dataInput id="_4_PriorityInput" name="Priority" />
        <inputSet>
          <dataInputRefs>_4_CommentInput</dataInputRefs>
          <dataInputRefs>_4_SkippableInput</dataInputRefs>
          <dataInputRefs>_4_TaskNameInput</dataInputRefs>
          <dataInputRefs>_4_ContentInput</dataInputRefs>
          <dataInputRefs>_4_PriorityInput</dataInputRefs>
        </inputSet>
        <outputSet>
        </outputSet>
      </ioSpecification>
      <dataInputAssociation>
        <targetRef>_4_CommentInput</targetRef>
        <assignment>
          <from xs:type="tFormalExpression">You need to perform an evaluation for #{employee}</from>
          <to xs:type="tFormalExpression">_4_CommentInput</to>
        </assignment>
      </dataInputAssociation>
      <dataInputAssociation>
        <targetRef>_4_SkippableInput</targetRef>
        <assignment>
          <from xs:type="tFormalExpression">false</from>
          <to xs:type="tFormalExpression">_4_SkippableInput</to>
        </assignment>
      </dataInputAssociation>
      <dataInputAssociation>
        <targetRef>_4_TaskNameInput</targetRef>
        <assignment>
          <from xs:type="tFormalExpression">Performance Evaluation</from>
          <to xs:type="tFormalExpression">_4_TaskNameInput</to>
        </assignment>
      </dataInputAssociation>
      <dataInputAssociation>
        <targetRef>_4_ContentInput</targetRef>
        <assignment>
          <from xs:type="tFormalExpression"></from>
          <to xs:type="tFormalExpression">_4_ContentInput</to>
        </assignment>
      </dataInputAssociation>
      <dataInputAssociation>
        <targetRef>_4_PriorityInput</targetRef>
        <assignment>
          <from xs:type="tFormalExpression">1</from>
          <to xs:type="tFormalExpression">_4_PriorityInput</to>
        </assignment>
      </dataInputAssociation>
      <potentialOwner>
        <resourceAssignmentExpression>
          <formalExpression>mary</formalExpression>
        </resourceAssignmentExpression>
      </potentialOwner>
    </userTask>
    <userTask id="_5" name="Project Manager Evaluation" g:x="352" g:y="16" g:width="225" g:height="48" >
      <ioSpecification>
        <dataInput id="_5_CommentInput" name="Comment" />
        <dataInput id="_5_SkippableInput" name="Skippable" />
        <dataInput id="_5_TaskNameInput" name="TaskName" />
        <dataInput id="_5_ContentInput" name="Content" />
        <dataInput id="_5_PriorityInput" name="Priority" />
        <inputSet>
          <dataInputRefs>_5_CommentInput</dataInputRefs>
          <dataInputRefs>_5_SkippableInput</dataInputRefs>
          <dataInputRefs>_5_TaskNameInput</dataInputRefs>
          <dataInputRefs>_5_ContentInput</dataInputRefs>
          <dataInputRefs>_5_PriorityInput</dataInputRefs>
        </inputSet>
        <outputSet>
        </outputSet>
      </ioSpecification>
      <dataInputAssociation>
        <targetRef>_5_CommentInput</targetRef>
        <assignment>
          <from xs:type="tFormalExpression">You need to perform an evaluation for #{employee}</from>
          <to xs:type="tFormalExpression">_5_CommentInput</to>
        </assignment>
      </dataInputAssociation>
      <dataInputAssociation>
        <targetRef>_5_SkippableInput</targetRef>
        <assignment>
          <from xs:type="tFormalExpression">false</from>
          <to xs:type="tFormalExpression">_5_SkippableInput</to>
        </assignment>
      </dataInputAssociation>
      <dataInputAssociation>
        <targetRef>_5_TaskNameInput</targetRef>
        <assignment>
          <from xs:type="tFormalExpression">Performance Evaluation</from>
          <to xs:type="tFormalExpression">_5_TaskNameInput</to>
        </assignment>
      </dataInputAssociation>
      <dataInputAssociation>
        <targetRef>_5_ContentInput</targetRef>
        <assignment>
          <from xs:type="tFormalExpression"></from>
          <to xs:type="tFormalExpression">_5_ContentInput</to>
        </assignment>
      </dataInputAssociation>
      <dataInputAssociation>
        <targetRef>_5_PriorityInput</targetRef>
        <assignment>
          <from xs:type="tFormalExpression">1</from>
          <to xs:type="tFormalExpression">_5_PriorityInput</to>
        </assignment>
      </dataInputAssociation>
      <potentialOwner>
        <resourceAssignmentExpression>
          <formalExpression>john</formalExpression>
        </resourceAssignmentExpression>
      </potentialOwner>
    </userTask>
    <parallelGateway id="_6" name="Converge" g:x="603" g:y="55" g:width="49" g:height="49" gatewayDirection="Converging" />
    <endEvent id="_7" name="EndProcess" g:x="690" g:y="56" g:width="48" g:height="48" >
      <terminateEventDefinition/>
    </endEvent>

    <!-- connections -->
    <sequenceFlow id="_1-_2" sourceRef="_1" targetRef="_2" />
    <sequenceFlow id="_2-_3" sourceRef="_2" targetRef="_3" />
    <sequenceFlow id="_3-_4" sourceRef="_3" targetRef="_4" g:bendpoints="[295,120]" />
    <sequenceFlow id="_3-_5" sourceRef="_3" targetRef="_5" g:bendpoints="[295,39]" />
    <sequenceFlow id="_5-_6" sourceRef="_5" targetRef="_6" g:bendpoints="[627,40]" />
    <sequenceFlow id="_4-_6" sourceRef="_4" targetRef="_6" g:bendpoints="[627,121]" />
    <sequenceFlow id="_6-_7" sourceRef="_6" targetRef="_7" />

  </process>

</definitions>

 

要使用BPMN 2.0格式创建你自己的流程,你可以

  • 使 用Drools Eclipse插件向导创建一个新的流(Flow),并且在这个向导的最后页面,确保你选择了Drools 5.1 code compatibility。这将创建一个使用 BPMN XML格式的新流程,而不是老的规则流(RuleFlow)格式。但是请注意,这不是一个真的BPMN 2.0编辑器,因为它仍然使用了不同的属性。然而,它使用有效的BPMN 2.0 语法保存流程。还要注意,该编辑器并不支持所有已经被执行引擎支持的节点类型和属性 。

  • Oryx 是一个支持 BPMN 2.0格式的基于网页开源编辑器。我们已经把它嵌入到Guvnor中,用于BPMN 2.0流程的可视化和编辑。 你也可以使用Oryx编辑器(独立的或集成的)创建/编辑BPMN 2.0流程,然后导出为BPMN 2.0格式,所以能够执行它们。然而要注意,Oryx仍然使用BPMN 2.0 beta 1格式, 它们的实现是不完整的(尤其是导入/导出功能)。

  • 你也可以直接编写XML,手动创建你的BPMN 2.0流程文件。

 

下面的代码片断展示给你看,如何加载一个BPMN流程到你的知识库...

private static KnowledgeBase readKnowledgeBase() throws Exception {
  KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
  kbuilder.add(ResourceFactory.newClassPathResource("sample.bpmn"), ResourceType.BPMN2);
  return kbuilder.newKnowledgeBase();
}

 

... 以及如何执行这个流程。

 

KnowledgeBase kbase = readKnowledgeBase(); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test"); ksession.getWorkItemManager().registerWorkItemHandler("Human Task", new WSHumanTaskHandler()); // start a new process instance Map<String, Object> params = new HashMap<String, Object>(); params.put("employee", "krisv"); ksession.startProcess("com.sample.evaluation", params);

 

14.1  当前的限制

 

由 于BPMN 2.0规范还未定稿,BPMN2.0执行仍然是一个实验性功能。然而它使用与RuleFlow格式相同的执行引擎和结构(它只是另一个XML系列化格 式)。因此,所有可用于RuleFlow格式的功能与组件也适用于BPMN 2.0流程。在添加BPMN 2.0流程到你的知识库时,你只需要使用正确的ResourceType。因为规范还未定稿, 定义格式的XSD(XML Schemas Definition)仍有可能随规范的更新而改变(轻微地),所以如果你决定开始使用BPMN 2.0格式,要牢记这一点。

 

规 则的使用应该给你很多好处,由于规范为每个元素定义了确切格式(甚至执行语义)),因此它允许你跨工具共享你的流程,甚至能够跨引擎共享你的流程。然而在 这点上,不同的工具使用规范的不同中间版本是可能的。我们相信随着时间的推移,一旦规范定稿,这些问题会随之解决,并且所有人会使用相同版本的规范,但是 在这之前,你可能遭遇有关这个问题的兼容性问题。就此请多点耐心。

 

最后,BPMN 2.0规范定义了很多节点类型和属性,但是尽管如此,只使用由BPMN 2.0规范提供的结构表达一切是不可能的。然而,规范被设计成允许附加的节点类型、属性等等。虽然我们试图限制自定义扩展的使用为最低限度,我们有些时候 却必须定义定制属性,表达我们认为重要,但又不能由核心BPMN 2.0 语法表达的功能。下面的表,给出了已经从RuleFlow语言的功能移植到了BPMN 2.0 XML格式的一个概述。 绿色复选标记,指明该功能使用在BPMN 2.0 规范中的功能表达。橙色复选标记,指明我们用附加属性和/或元素扩展了BPMN 2.0 规范。如下表所示,已经支持大部分基本BPMN 2.0节点。我们决定了在默认时不能被BPMN 2.0表达的还没有实现的一些功能,例如,on-entry / on-exit 动作或状态节点。 当然,我们以后会决定,我们是否在将来希望支持这些功能用于 BPMN 2.0流程。

 

表 14.1 关键字

FeatureDrools BPMNDrools Flow
A. Process-level    
     
Imports    
Function Imports    
Variable    
- primitive Java types    
- Java object types    
- default value    
Swimlanes    
Exception handlers    
- fault name    
- bind to variable    
- action    
     
B. Nodes    
     
1. Start Node    
- rule trigger    
- signal trigger    
- parameter mapping    
     
2. End Node    
- terminate    
     
3. Action Node    
- Java dialect    
* access to variables, global, context    
- MVEL dialect    
* access to variables, global, context    
     
4. RuleSet Node    
- timers    
     
5. Split Node    
- AND    
- XOR    
- OR    
- Java code constraints    
- MVEL code constraints    
- rule constraints    
- constraint names    
- constraint priorities    
     
6. Join Node    
AND    
XOR    
Discriminator    
n-of-m    
     
7. State Node    
- timers    
- on entry actions    
- on exit actions    
- automatic transition constraints    
- manual transition signal    
     
8. SubProcess Node    
- timers    
- on entry actions    
- on exit actions    
- wait for completion    
- independant    
- parameter mapping (in/out)    
- dynamic process id    
     
9. WorkItem Node    
- parameters    
- parameter mapping (in/out)    
- timers    
- on entry actions    
- on exit actions    
- wait for completion    
     
10. Timer Node    
- delay    
- period    
     
11. Human Task Node (also see WorkItem Node)    
- swimlane    
     
12. Composite Node    
- timers    
- on entry actions    
- on exit actions    
- variables    
- exception handlers    
- multiple entry points    
- multiple exit points    
     
13. ForEach Node    
- bind to variable    
- wait for completion    
- multiple entry points    
- multiple exit points    
     
14. Event Node    
- bind to variable    
- internal / external    
- event filters    
     
15. Fault Node    
- fault name    
- fault data    
     
Graphical information (x, y, width, height)    
     
C. Connections    
From, To    
From type    
To type    
Graphical information (bendpoints)    
posted @ 2011-11-09 17:56  skyme  阅读(1125)  评论(0)    收藏  举报