jbpm5.1介绍(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可以定义使用一个子进程子范围定义变量只在该范围内节点访问

每当访问一个变量,这个进程将寻找合适的变量范围定义变量变量作用域嵌套不允许的。节点总是会寻找其父容器一个变量如果无法找到该变量,一个人的父容器等等,直到达到流程实例本身如果无法找到该变量读访问产量写访问会产生错误消息继续执行的过程

变量可以用各种方式

  • 流程级别的变量可以设置启动时提供的参数映射到thestartProcess方法调用一个过程这些参数将作为进程范围变量
  • 脚本操作,只需直接使用脚本本地参数变量的名称可以访问变量。例如,如果程序定义了一个变量类型org.jbpm.Person”的过程中在这个过程中脚本可以访问此直接: person.setAge(10);更改一个脚本中的变量可以通过知识背景下kcontext.setVariable(variableName, value);
  • 服务任务重复使用过程可以通过向外界另一个进程实例过程变量变量映射一个传出参数例如,服务任务参数映射可以定义的过程变量x被映射到一个任务参数y对前被调用服务您还可以注入一个硬编码参数字符串使用{表达式}过程变量值例如,可以定义一个人任务描述您需要联络人#{person.getName()}其中是一个过程变量这个表达式将取代实际名称服务时需要调用同样的服务可重复使用的子进程结果也可以复制使用结果映射到一个变量
  • 各种其他节点也可以访问数据。例如事件节点可以存储在变量事件关联的数据检查更多信息,不同的节点类型的属性

最后,流程和规则进入全局,即全局变量知识会话数据的全局行动就像变量直接访问全局需要定义作为这一进程的一部分才可以使用例如按一下指定动作脚本在Eclipse行动的属性编辑器全局按钮您可以定义全局您还可以设置一个全球从外面使用ksession.setGlobal名称,值从内部使用kcontext.getKnowledgeRuntime()过程脚本价值在setglobal名称,值;

约束

约束可用于在不同的地点你的流程例如一个不同的网关 jBPM支持两种类型的约束

  • 守则约束的布尔表达式他们到达直接评价我们目前支持两种方言表达这些代码限制Java和MVEL Java和MVEL代码限制直接访问,并在这个过程中定义全局变量下面一个有效的Java代码的约束在这个过程中一个变量一个例子return person.getAge()>20;一个类似的例子是一个有效MVEL代码约束:return person.age > 20;
  • 规则约束等于正常Drools的规则条件他们使用了Drools规则语言语法表达可能复杂的约束这些规则可以任何其他规则是指工作内存中数据他们还可以直接全局下面一个有效的规则约束例子:Person( age > 20 )

规则约束没有直接访问内部的过程定义的变量不过这是可能加入流程实例工作记忆你的规则约束匹配过程实例的规则约束当前进程的实例我们已经添加了特殊的逻辑,以确保变量类型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规范共同的可执行文件”子类一些额外的元素属性我们相信扩展定义属性以及在这方面宝贵下面可以找到全套支持元素和属性但它包含元素

流程对象包括

  • 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
      • 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
        • Inclusive
        • Parallel
        • Event-Based
      • Converging             
        • Exclusive
        • Parallel
    • Lanes
  • Data
    • Java type language
    • Process properties
    • Embedded Sub-Process properties
    • Activity properties
  • Connecting objects
    • Sequence flow

例如,考虑下面的“你好世界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"  />
         <di:waypoint x= "240"  y= "240"  />
         <di:waypoint x= "282"  y= "110"  />
       </bpmndi:BPMNEdge>
     </bpmndi:BPMNPlane>
   </bpmndi:BPMNDiagram>
 
</definitions>

创建自己的过程使用BPMN 2.0的格式你可以

创建一个新的流文件使用Drools Eclipse插件向导向导的最后一页确保选择的Drools5.1的代码兼容性使用BPMN 2.0的XML格式这将创建一个新的进程但是请注意,这是不完全的BPMN 2.0编辑,因为它仍然使用不同属性的名称但它确实保存过程中使用有效BPMN2.0的语法另外请注意,编辑器不支持所有节点类型和已执行引擎支持的属性

设计师是一个开源基于Web的编辑器,支持BPMN2.0格式我们已经嵌入到Guvnor BPMN 2.0的流程可视化和编辑你可以使用Designer独立或集成创建/编辑BPMN 2.0流程然后出口到BPMN 2.0的格式或将其保存Guvnor,使他们能够执行

正在创建一个BPMN2的Eclipse插件支持完整的BPMN2规范这是目前仍在开发中只支持数量有限结构和属性,但已经可以用来创建简单BPMN2流程创建一个新的BPMN2的这个编辑器文件使用向导例子创建一个新的BPMN2的文件,这将产生一个BPMN2文件和一个。珠三角文件包含图形信息双击珠三角文件使用的图形化编辑编辑该文件

通过直接写入XML您可以随时手动创建BPMN 2.0的流程文件您可以BPMN 2.0的XSD验证你的流程语法Eclipse插件使用验证器来检查你的模型的语法和完整性

下面的代码片段显示如何加载到知识库一个BPMN2的过程......

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

 

... ...如何执行此过程中......

KnowledgeBase kbase = createKnowledgeBase();
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
ksession.startProcess( "com.sample.HelloWorld" );

持久化和转换

jBPM的持久存储允许某些信息流程的运行时状态历史信息

1)运行时状态

每当启动一个过程一个过程实例被创建,它代表的过程这种特定情况下执行例如,执行过程中指定如何处理销售订单一个流程实例创建要求每个销售流程实例代表当前的执行状态,这种特定情况下包含所有相关信息流程实例注意,它仅包含最小运行状态需要继续这一进程的实例执行一段时间后,但它不包括这一进程的实例历史信息如果该信息不再需要流程实例

执行过程运行状态可以持久的,例如在数据库中这使得恢复意外故障情况所有正在运行的进程执行状态或者暂时从内存中删除正在运行的实例在一段时间后恢复它们 jBPM的允许您插入不同持久性策略默认情况下,如果你不配置流程引擎否则流程实例没有持久性

二进制持久性

jBPM提供了一个二进制持久性机制允许您保存为二进制数据一个流程实例状态通过这种方式,所有正在运行的进程实例状态总是可以被储存一个持久位置注意这些二进制数据通常都比较小,因为它们只包含最小流程实例执行状态对于一个简单的过程实例,这通常包含一个或几个节点的实例任何节点当前正在执行,并且可能的话,一些变量的值

安全点

一个流程实例状态存储流程引擎执行所谓的“安全点每当一个流程实例执行启动或一个等待状态延续发引擎的收益可以执行直到没有更多的行动在这一点上,引擎已达到未来安全状态坚持存储过程实例状态所有其他进程有可能受到影响实例

配置持久性

默认情况下,流程引擎保存运行时的数据持续然而,它可以通过非常简单的配置做到这一点,通过添加一个配置文件和必要的依赖基于Java持久性APIJPA)的持久性本身,因此可以几个持久性机制我们使用Hibernate在默认有情况下H2数据库来存储数据你可以选择你自己选择

首先,你需要添加必要的依存关系到你的classpath如果你使用Eclipse IDE你可以通过添加JAR文件到你的jBPM运行时目录通过手动添加这些依赖关系到您的项目首先,你需要的JAR文件与jBPM持久化jpa.jar包含用于保存运行时的状态必要时代码接下来,您还需要其他各种依赖关系具体取决于您使用持久性解决方案和数据库与Hibernate作为JPA持久性提供程序H2数据库和JTA的事务管理Bitronix默认组合下面的列表是需要额外的依赖

  • jbpm-persistence-jpa (org.jbpm)
  • drools-persistence-jpa (org.drools)
  • persistence-api (javax.persistence)
  • hibernate-entitymanager (org.hibernate)
  • hibernate-annotations (org.hibernate)
  • hibernate-commons-annotations (org.hibernate)
  • hibernate-core (org.hibernate)
  • dom4j (dom4j)
  • jta (javax.transaction)
  • btm (org.codehaus.btm)
  • javassist (javassist)
  • slf4j-api (org.slf4j)
  • slf4j-jdk14 (org.slf4j)
  • h2 (com.h2database)
  • commons-collections (commons-collections)

接下来,您需要配置jBPM引擎在必要时保存引擎状态要做到这一点最简单的方法使用JPAKnowledgeService创建您的知识会话基于知识基础知识的会话配置(如有必要)和环境环境需要包含实体管理器工厂引用例如:

// create the entity manager factory and register it in the environment
EntityManagerFactory emf =
     Persistence.createEntityManagerFactory( "org.jbpm.persistence.jpa"  );
Environment env = KnowledgeBaseFactory.newEnvironment();
env. set ( EnvironmentName.ENTITY_MANAGER_FACTORY, emf );
 
// create a new knowledge session that uses JPA to store the runtime state
StatefulKnowledgeSession ksession =
     JPAKnowledgeService.newStatefulKnowledgeSession( kbase, null , env );
int  sessionId = ksession.getId();
 
// invoke methods on your method here
ksession.startProcess( "MyProcess"  );
ksession.dispose();

您还可以YSEJPAKnowledgeService重新创建基于一个特定的会话ID会话

// recreate the session from database using the sessionId
ksession = JPAKnowledgeService.loadStatefulKnowledgeSession( sessionId, kbase, null , env );

注意,我们只保存最小状态,需要继续在以后的某个执行过程实例这意味着例如,包含已经执行节点信息,如果该信息不再是相关的已完成或中止从数据库中删除该进程的实例。如果你想搜索历史相关的信息应该使用的历史记录,后面会解释

需要添加一个持久性配置到你的classpath配置JPA的使用HibernateH2数据库(或您的偏好名为persistence.xml的META - INF目录,如下所示对于如何改变自己的配置更多细节,我们JPA和Hibernate文档了解更多信息

<?xml version= "1.0"  encoding= "UTF-8"  standalone= "yes" ?>
<persistence
   version= "1.0"
   xsi:schemaLocation=
     "http: //java.sun.com/xml/ns/persistence
      http: //java.sun.com/xml/ns/persistence/persistence_1_0.xsd
      http: //java.sun.com/xml/ns/persistence/orm
      http: //java.sun.com/xml/ns/persistence/orm_1_0.xsd"
 
   <persistence-unit name= "org.jbpm.persistence.jpa" >
     <provider>org.hibernate.ejb.HibernatePersistence</provider>
     <jta-data-source>jdbc/processInstanceDS</jta-data-source>
     < class >org.drools.persistence.info.SessionInfo</ class >
     < class >org.jbpm.persistence.processinstance.ProcessInstanceInfo</ class >
     < class >org.drools.persistence.info.WorkItemInfo</ class >
 
     <properties>
       <property name= "hibernate.dialect"  value= "org.hibernate.dialect.H2Dialect" />
       <property name= "hibernate.max_fetch_depth"  value= "3" />
       <property name= "hibernate.hbm2ddl.auto"  value= "update" />
       <property name= "hibernate.show_sql"  value= "true" />
       <property name= "hibernate.transaction.manager_lookup_class"
                 value= "org.hibernate.transaction.BTMTransactionManagerLookup" />
     </properties>
   </persistence-unit>
</persistence>

这个配置文件是指所谓的“JDBC / processInstanceDS数据源下面的Java代码片段可以用来设置该数据源,在这里我们使用的是基于文件的H2数据库

PoolingDataSource ds = new  PoolingDataSource();
ds.setUniqueName( "jdbc/testDS1" );
ds.setClassName( "org.h2.jdbcx.JdbcDataSource" );
ds.setMaxPoolSize(3);
ds.setAllowLocalTransactions( true );
ds.getDriverProperties().put( "user" , "sa" );
ds.getDriverProperties().put( "password" , "sasa" );
ds.getDriverProperties().put( "URL" , "jdbc:h2:file:/NotBackedUp/data/process-instance-db" );
ds.init();

如果你部署到应用服务器,通常可以deploy目录中的配置文件例如,创建一个数据源

<?xml version= "1.0"  encoding= "UTF-8" ?>
<datasources>
   <local-tx-datasource>
     <jndi-name>jdbc/testDS1</jndi-name>
     <connection-url>jdbc:h2:file:/NotBackedUp/data/process-instance-db</connection-url>
     <driver- class >org.h2.jdbcx.JdbcDataSource</driver- class >
     <user-name>sa</user-name>
     <password>sasa</password>
   </local-tx-datasource>
</datasources>

2)转换

只要你不提供您的应用程序事务边界,发动机对发动机会自动执行一个单独的事务每个方法调用如果这种行为是可以接受的,你不需要做别的你可以,但是也可以指定自己事务边界例如,这可以让你组合成一个事务多个命令

您需要注册后环境使用用户定义事务之前事务管理器下面的代码示例使用Bitronix事务管理接下来,我们使用Java事务APIJTA),指定事务边界,如下图所示

// create the entity manager factory and register it in the environment
EntityManagerFactory emf =
     Persistence.createEntityManagerFactory( "org.jbpm.persistence.jpa"  );
Environment env = KnowledgeBaseFactory.newEnvironment();
env. set ( EnvironmentName.ENTITY_MANAGER_FACTORY, emf );
env. set ( EnvironmentName.TRANSACTION_MANAGER,
          TransactionManagerServices.getTransactionManager() );
 
// create a new knowledge session that uses JPA to store the runtime state
StatefulKnowledgeSession ksession =
     JPAKnowledgeService.newStatefulKnowledgeSession( kbase, null , env );
 
// start the transaction
UserTransaction ut =
   (UserTransaction) new  InitialContext().lookup( "java:comp/UserTransaction"  );
ut.begin();
 
// perform multiple commands inside one transaction
ksession.insert( new  Person( "John Doe"  ) );
ksession.startProcess( "MyProcess"  );
 
// commit the transaction
ut.commit();

流程定义

流程定义文件通常被写在一个XML格式这些文件可以很容易地存储在文件系统在开发过程中但是,只要你想使知识在生产中一个或多个引擎访问我们建议使用(逻辑)你的知识集中在一个或多个知识库GuvnorDrools的一个项目,提供这一点它由一个仓库用于存储不同类型的知识不仅流程定义规则,对象模型它允许使用WebDAV知识运用知识代理当创建一个自动下载信息Guvnor便于检索的知识基础,提供了一个Web应用程序,允许业务用户可以查看和更新知识信息信息如何做到这一点更多信息检索的Drools Guvnor文档

历史记录

在许多情况下是非常有用如果没有必要存储流程实例的执行信息使这一信息可用于事后例如,为了验证一个特定的流程实例执行过什么行动监测和分析一个特定的进程效率运行时数据库存储历史信息通常不是一个好主意,因为这将导致不断增长运行数据监测和分析,查询可能会影响运行时引擎性能这就是为什么历史流程实例的执行信息是分开存储

执行信息历史记录创建基于流程引擎在执行过程中生成的事件 jBPM运行时引擎提供了一个通用机制,听取各种不同的事件必要的信息可以很容易地这些事件提取持久化例如在数据库中过滤器可用于存储找到相关信息

存储在数据库中处理事件

jBPM的BAM模块包含一个事件监听器进程相关的信息存储在一个数据库直接使用JPA或Hibernate该数据库包含两个表,一个流程实例信息一个节点实例的信息见下图

1.ProcessInstanceLog列出的过程实例ID进程(定义ID,开始日期和(如适用)所有流程实例结束日期

2.NodeInstanceLog此表包含哪些节点实际上每个流程实例执行更详细的信息每当一个节点实例进入进来的连接通过传出连接退出,这些信息是存储在此表中对于这一点,存储过程实例ID和正在执行流程实例进程ID节点实例ID和相应的节点ID节点实例中的问题在这个过程中定义最后,事件的类型0=输入,1 =退出事件的日期以及存储

日志数据库在这样的历史进程信息您需要注册会话(或工作记忆记录像这样

StatefulKnowledgeSession ksession = ...;
JPAWorkingMemoryDbLogger logger = new  JPAWorkingMemoryDbLogger(ksession);
 
// invoke methods one your session here
 
logger.dispose();

请注意,此记录像其他任何审计记录器这意味着你可以调用方法addFilter,以确保只有相关信息存储在数据库中添加一个或多个过滤只有所有过滤器接受信息会出现在数据库中。它不再需要应将该记录器

指定存储信息数据库修改的文件persistence.xml文件包括审计日志以及ProcessInstanceLogNodeInstanceLogVariableInstanceLog,如下所示

<?xml version= "1.0"  encoding= "UTF-8"  standalone= "yes" ?>
<persistence
   version= "1.0"
   xsi:schemaLocation=
     "http: //java.sun.com/xml/ns/persistence
      http: //java.sun.com/xml/ns/persistence/persistence_1_0.xsd
      http: //java.sun.com/xml/ns/persistence/orm
      http: //java.sun.com/xml/ns/persistence/orm_1_0.xsd"
 
   <persistence-unit name= "org.jbpm.persistence.jpa" >
     <provider>org.hibernate.ejb.HibernatePersistence</provider>
     <jta-data-source>jdbc/processInstanceDS</jta-data-source>
     < class >org.drools.persistence.info.SessionInfo</ class >
     < class >org.jbpm.persistence.processinstance.ProcessInstanceInfo</ class >
     < class >org.drools.persistence.info.WorkItemInfo</ class >
     < class >org.jbpm.process.audit.ProcessInstanceLog</ class >
     < class >org.jbpm.process.audit.NodeInstanceLog</ class >
     < class >org.jbpm.process.audit.VariableInstanceLog</ class >
 
     <properties>
       <property name= "hibernate.dialect"  value= "org.hibernate.dialect.H2Dialect" />