JBPM5学习资料3(流程启动)
在您好的应用程序中使用一个新的流程
流程处理
(1)你需要建立一个知识库,其中包含过程定义
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add( ResourceFactory.newClassPathResource(
"MyProcess.bpmn2"
),
ResourceType.BPMN2 );
|
加入你的进程生成器(可以添加多个进程)后,您可以创建一个新的知识基础,这样的:
KnowledgeBase kbase = kbuilder.newKnowledgeBase();
|
请注意,这将抛出一个异常,如果知识库包含错误(因为它不能正确地分析您的流程)。
(2)你需要创建一个会话,沟通与流程引擎和启动过程的启动过程。
启动过程:启动一个特定的进程,你会需要调用您的会话的startProcess方法,并传递您要启动的进程的ID。例如:
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
ksession.startProcess(
"com.sample.hello"
);
|
startProcess方法的参数是需要启动的进程ID。当定义一个过程,这需要作为一个过程的财产(例如在Eclipse的属性视图显示,当您单击过程中的背景画布)指定进程ID。
当您启动的过程中,你可以指定额外的参数,用来传递额外的输入数据的过程中,使用startProcess(弦乐进程ID,地图参数)方法。额外的参数是一个名称 - 值对的集合。这些参数将被复制到新创建的进程实例的顶层变量的过程,所以他们可以在你的进程余下的直接访问。
数据
虽然流程图上指定的过程控制流的重点,它通常也有必要的过程,从数据的角度看。在整个执行过程中,数据可以检索,存储,传递和使用。
对于运行时的数据,存储在执行过程中中,过程变量都可以使用。变量是一个名称和一个数据类型定义。这可能是一个基本数据类型,如布尔,INT,或String,或任何Object的子类。变量可以定义一个变量的范围内。顶层的范围是过程本身的变量的范围。Subscopes可以定义使用一个子进程。子范围定义的变量只在该范围内的节点访问。
每当访问一个变量,这个进程将寻找合适的变量范围定义变量。变量作用域的嵌套是不允许的。节点总是会寻找其父容器中的一个变量。如果无法找到该变量,它会看,一个人的父容器,等等,直到达到流程实例本身。如果无法找到该变量,读访问产量空,写访问会产生错误消息,继续执行的过程。
变量可以用各种方式:
最后,流程和规则都进入到全局,即全局变量和知识会话中的数据。的全局在行动就像变量直接访问。全局需要定义作为这一进程的一部分,才可以使用。例如,按一下指定动作脚本在Eclipse行动的属性编辑器时,全局按钮您可以定义的全局。您还可以设置一个全球从外面使用ksession.setGlobal(名称,值),或从内部使用kcontext.getKnowledgeRuntime()的过程脚本的价值在setglobal(名称,值);
约束
约束可用于在不同的地点,在你的流程,例如在一个不同的网关。 jBPM支持两种类型的约束:
规则约束,没有直接访问内部的过程中定义的变量。不过,这是有可能加入流程实例工作记忆在你的规则约束和匹配过程实例内的规则约束,指当前进程的实例。我们已经添加了特殊的逻辑,以确保变量的类型WorkflowProcessInstance流程实例将只匹配当前进程的实例,而不是在工作内存中的其他进程实例。请注意,不过,你是负责自己插入到会话的过程实例,可能的话,更新它,例如,使用Java代码或在你的进程进入或退出或明确的行动。规则的约束下面的例子将一个人在变量“名称”的过程中存储的值相同的名称搜索:
processInstance : WorkflowProcessInstance()
Person( name == ( processInstance.getVariable(
"name"
) ) )
# add more constraints here ...
|
动作角本
动作脚本可以使用不同的方式:
操作全局和过程和预定义变量kcontext的定义的变量的访问。此变量的类型org.drools.runtime.process.ProcessContext,可用于多个任务:
获取当前节点的实例(如适用)。节点的实例,如它的名称和类型的数据,可以查询。您还可以取消当前节点的实例。
NodeInstance node = kcontext.getNodeInstance();
String name = node.getNodeName();
|
获取当前进程的实例。可以查询流程实例数据(名称,ID,进程ID等),中止或暗示内部事件。
ProcessInstance proc = kcontext.getProcessInstance();
proc.signalEvent( type, eventObject );
|
获取或设置变量的值。
访问知识库中运行时,允许你不喜欢的东西开始一个进程,信号(外部)事件,插入数据,等
jBPM的目前支持两种方言,Java和MVEL。 Java的行动应该是有效的Java代码。 MVEL行动可以使用的业务脚本语言MVEL表达的行动。 MVEL接受任何有效的Java代码,但此外提供支持嵌套的参数访问(例如,person.name,而不是person.getName()),和许多其他的脚本改进。因此,MVEL表达式为商业用户更方便。例如,一个动作,打印出的人在“请求者”的过程变量的名称看起来像这样:
// Java dialect
System.
out
.println( person.getName() );
// MVEL dialect
System.
out
.println( person.name );
|
活动
在执行过程中,流程引擎可以确保所有相关的任务是根据工艺方案执行,请求执行的工作项目,并等待结果。然而,它也有可能这一进程应作出回应,不直接由流程引擎要求的事件。明确代表这些事件的过程中允许指定过程中应如何应对此类事件的过程作者。
事件有一个类型,可能与他们相关的数据。用户可以自由定义自己的事件类型及其相关的数据。
一个进程可以指定如何使用消息事件响应的事件。一个事件节点需要指定类型的事件节点感兴趣,它也可以定义一个变量的名字,这将收到与该事件相关的数据。这使得在这个过程中的后续节点访问事件数据,并根据该数据,采取适当的行动。
事件可能标志着一个在多种方式的过程正在运行的实例:
内部事件:任何一个进程内的行动(例如,行动节点的行动,或一些节点上进入或退出行动)信号的内部事件的发生,周围的流程实例,使用类似的代码以下内容:
kcontext.getProcessInstance().signalEvent(type, eventData);
|
外部事件:事件通知一个流程实例可以从外面用,如代码:
processInstance.signalEvent(type, eventData);
|
使用事件相关,而是直接通知一个流程实例的外部事件,它也可以让发动机自动确定流程实例可能会使用事件的相关性,这是基于事件类型的事件感兴趣。这样的事件发生时,一个流程实例包含事件节点听某种类型的外部事件通知。信号此类事件的流程引擎,写代码,如:
ksession.signalEvent(type, eventData);
|
事件也可以被用来启动一个进程。每当消息开始事件定义一个特定类型的事件触发,将会启动新的流程实例,每次事件的类型,信号流程引擎。
计时器
计时器等待一个预定义的时间,触发前,一次或多次。他们可以使用一段时间后触发一定的逻辑关系,或定期重复某些动作。
定时器节点设置一个延迟和一个时期。延迟指定的时间节点激活后等待触发定时器首次。这一时期定义随后触发激活之间的时间。期间,一个在单次触发定时器0的结果。
表达的形式应[#][#H] [#M] [#S] [#[MS]。这意味着,您可以指定天,小时,分钟,秒和multiseconds(这是默认的,如果你不指定任何)的数量。例如,表达“1H”将等待触发定时器(再次)一小时。
负责确保在适当的时候触发,定时器得到的定时服务。定时器也被取消,这意味着将不再被触发定时器。
定时器可用于在一个进程内的两个方面:
计时器事件可能会增加流动过程。其激活启动定时器,它触发时,一次或多次,它会激活定时器节点的继任者。这意味着,以积极的时期传出连接定时器触发多次。取消定时器节点也取消了相关的计时器,在这之后没有更多的触发会发生。
定时器可以与一个子进程,作为一个边界事件。但是,这是目前唯一可能直接在XML。我们将加入支持在新的BPMN2编辑器以图形方式指定。
更新流程
随着时间的推移,流程可能演变例如,因为这个过程本身需要加以改进,或由于不断变化的需求。其实,你真的不能更新的过程,你只能部署一个新版本的过程中,旧的过程将依然存在。这是因为现有的流程实例,可能还需要这一过程定义。因此,新的过程,应该有一个不同的ID,虽然名称可能是相同的,可以使用的版本参数表明,当一个进程更新(版本参数只是一个字符串,而不是进程的框架本身的验证,所以你可以选择自己的格式,用于指定小/大的更新等)。
每当一个更新过程,重要的是,以确定哪些应该发生到已经运行的进程实例。有不同的策略之一,可以考虑为每个运行实例:
步骤操作:正在运行的进程实例的收益为正常,因为它是定义流程实例启动时,下面的过程(定义)。因此,已经运行的实例会进行过程中,仿佛从来没有更新。新的实例可以开始使用更新的过程。
中止并重新启动已经运行的实例被中止。如果有必要,可以重新启动的过程实例,使用新的流程定义。
传输:过程实例迁移到新的流程定义,含义, - 一旦它被成功迁移 - 将继续执行的基础上更新的过程逻辑。
默认情况下,jBPM的使用进行的方法,这意味着可以部署同一进程的多个版本,但现有的流程实例将简单的启动流程实例时所使用的流程定义的基础上继续执行。总是可以被中止正在运行的进程实例,以及当然,在使用过程中的管理API。过程实例迁移是比较困难的,是在下面的段落解释。
流程实例的迁移
一个流程实例包含所有运行中的信息,需要继续执行一些在稍后的时间点。这包括所有链接到这个过程实例(如变量)的数据,而且在这个过程中图的当前状态。对于当前处于活动状态的每个节点,一个节点的实例是用来表示。这个节点的实例,也可以包含额外的状态链接到仅该特定节点的执行。有不同类型的节点实例,每个类型的节点之一。
一个流程实例只包含运行时的状态,并链接到一个特定的进程(间接使用ID引用)表示在执行这个流程实例(这明确的定义和运行时状态分离时,需要遵循的流程逻辑允许重用的跨越这个过程中,最大限度地减少运行时的状态为基础的所有流程实例)的定义。因此,更新一个正在运行的进程实例,所以它使用了新的进程逻辑,而不是旧到新的版本是一个简单的改变从旧到新的ID引用的进程ID的问题。
但是,这并没有考虑到流程实例的状态(变量实例和节点实例)以及可能需要迁移。仅扩展的过程和所有现有的等待状态保持的情况下,这是非常简单,流程实例的运行状态并不需要改变。然而,也有可能是一个更sofisticated的映射是必要的。例如,现有的等待状态时被删除,或分割成多个等待状态,等待在该国现有流程实例,不能简单地更新。或者引入一个新的进程变量时,该变量可能需要initiazed正确的,因此它可以在(更新)过程中的其余部分使用。
WorkflowProcessInstanceUpgrader可以使用工作流过程实例升级到一个新的流程实例。当然,您需要提供的流程实例和新的进程ID。默认情况下,jBPM将自动新节点具有相同的ID实例映射旧节点实例。但是你可以提供一个旧的(唯一的)节点ID映射到新的节点ID。惟一的节点ID的节点ID,其父母的节点ID(冒号inbetween)之前,允许唯一标识一个节点时使用复合节点(节点ID节点容器内只有独特。新的节点ID简直是在新的节点ID节点的容器(所以这里没有惟一的节点ID,只是新的节点ID)。下面的代码片段显示了一个简单的例子。
// create the session and start the process "com.sample.process"
KnowledgeBuilder kbuilder = ...
StatefulKnowledgeSession ksession = ...
ProcessInstance processInstance = ksession.startProcess(
"com.sample.process"
);
// add a new version of the process "com.sample.process2"
kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(..., ResourceType.BPMN2);
kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
// migrate process instance to new version
Map<String, Long> mapping =
new
HashMap<String, Long>();
// top level node 2 is mapped to a new node with id 3
mapping.put(
"2"
, 3L);
// node 2, which is part of composite node 5, is mapped to a new node with id 4
mapping.put(
"5.2"
, 4L);
WorkflowProcessInstanceUpgrader.upgradeProcessInstance(
ksession, processInstance.getId(),
"com.sample.process2"
, mapping);
|
如果这种映射仍然不足,你仍然可以描述自己的自定义映射器,针对具体情况。请务必先断开流程实例,相应地改变状态,然后重新连接的过程实例,类似如何WorkflowProcessinstanceUpgrader它。
业务流程模型和符号(BPMN)2.0规范
BPMN的主要目标是提供一个符号,是所有业务用户容易理解的,
从创建进程的初稿,业务分析师,技术开发
负责实施的技术,将执行这些进程,并最终到
商界人士将管理和监视这些进程。“
|
业务流程模型和符号(BPMN)2.0规范,不仅定义了一个标准,就如何以图形方式表示业务流程(如BPMN1.x的)是OMG规范,但现在还包括为执行定义的元素语义,和XML格式(股)如何存储过程定义。
jBPM5允许执行使用的BPMN 2.0的XML格式定义的流程。这意味着,您可以使用所有不同的jBPM5模具模型,执行,管理和监控您的业务流程,指定可执行的业务流程中使用的BPMN2.0格式。事实上,完整的BPMN 2.0规范还包括如何表示像编排和和协作的事情的细节。然而,jBPM项目的重点部分,可用于指定可执行流程的规范。
BPMN中的可执行文件的进程,包括不同类型的节点被连接到对方使用顺序流。 BPMN 2.0规范定义了三种主要类型的节点:
事件:它们用于模型中的特定事件的发生。这可能是一个开始事件(即用来指示的过程中开始),结束事件(定义过程结束,或该子流)和中间事件(指示的执行过程中可能出现的事件过程)。
活动:这些定义,需要在执行过程中执行不同的动作。存在不同类型的任务,对活动的类型取决于您尝试模型(如人工的任务,服务任务等)和actvities也可以嵌套(使用不同类型的子进程)。
网关:可以被用来定义多个路径的过程中。根据网关类型,这些可能表明并行执行,选择等
jBPM5没有实现在BPMN 2.0规范定义的所有元素和属性。然而,我们支持一个显著的子集,包括可执行的流程内,可使用的最常见的节点类型。这包括几乎所有元素,并在BPMN 2.0规范的“共同的可执行文件”子类与一些额外的元素和属性,我们相信扩展,定义的属性,以及在这方面的宝贵。下面可以找到全套支持的元素和属性,但它包含了像元素:
流程对象包括
例如,考虑下面的“你好世界”BPMN 2.0的过程中,它什么也不做,写一个“Hello World”的说法时,过程开始。
这个过程的可执行版本使用BPMN 2.0的XML表示会看起来像这样:
<?xml version=
"1.0"
encoding=
"UTF-8"
?>
<definitions id=
"Definition"
targetNamespace=
"http://www.example.org/MinimalExample"
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:bpmndi=
"http://www.omg.org/spec/BPMN/20100524/DI"
xmlns:dc=
"http://www.omg.org/spec/DD/20100524/DC"
xmlns:di=
"http://www.omg.org/spec/DD/20100524/DI"
xmlns:tns=
"http://www.jboss.org/drools"
>
<process processType=
"Private"
isExecutable=
"true"
id=
"com.sample.HelloWorld"
name=
"Hello World"
>
<!-- nodes -->
<startEvent id=
"_1"
name=
"StartProcess"
/>
<scriptTask id=
"_2"
name=
"Hello"
>
<script>System.
out
.println(
"Hello World"
);</script>
</scriptTask>
<endEvent id=
"_3"
name=
"EndProcess"
>
<terminateEventDefinition/>
</endEvent>
<!-- connections -->
<sequenceFlow id=
"_1-_2"
sourceRef=
"_1"
targetRef=
"_2"
/>
<sequenceFlow id=
"_2-_3"
sourceRef=
"_2"
targetRef=
"_3"
/>
</process>
<bpmndi:BPMNDiagram>
<bpmndi:BPMNPlane bpmnElement=
"Minimal"
>
<bpmndi:BPMNShape bpmnElement=
"_1"
>
<dc:Bounds x=
"15"
y=
"91"
width=
"48"
height=
"48"
/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement=
"_2"
>
<dc:Bounds x=
"95"
y=
"88"
width=
"83"
height=
"48"
/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement=
"_3"
>
<dc:Bounds x=
"258"
y=
"86"
width=
"48"
height=
"48"
/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement=
"_1-_2"
>
<di:waypoint x=
"39"
y=
"115"
/>
<di:waypoint x=
"75"
y=
"46"
/>
<di:waypoint x=
"136"
y=
"112"
/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement=
"_2-_3"
>
<di:waypoint x=
"136"
y=
"112"
/>
|