KIE

作者: 金刚_30bf | 来源:发表于2018-08-26 13:49 被阅读0次

    版本 7.9.0

    KIE 生态

    图片.png

    OptaPlanner 是一个本地搜索和优化的工具,独立于Drools Planner 。
    UberFire 是新的workbench工程,提供类似Eclipse工作台功能。
    KIE-WB 是整合了Guvnor 、drools、jbpm的uber工作台。jbpm-wb是虚的。

    生命周期

    • Author 创作
      使用DRL、BPMN2、决策表、类进行知识创作
    • 构建
      将创作的知识构建为可部署的单元, JAR。
    • 测试
    • 部署
    • 使用 、管理

    使用maven

    使用maven构建, 遵循maven的实践规则。 KIE工程可以作为maven工程或module。 spring 中提供xml配置来代替元数据配置META-INF/kmodule.xml。

    maven构建时不提供校验规则的机制, 可以通过插件实现 kie-maven-plugin 。

    Kie项目具有普通maven的工程结构,唯一特点是需要包含一个kmodule.xml文件, 此文件必须放在Maven项目的resources / META-INF文件夹中,而所有其他Kie工件(如DRL或Excel文件)必须存储在resources文件夹或其下的任何其他子文件夹中。

    由于工程使用默认的配置,因此最简单的kmodule.xml文件如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <kmodule xmlns="http://www.drools.org/xsd/kmodule"/>
    

    这种情况下,kmodule将包含一个默认的KieBase 。 所有存储在resources文件夹下及其子文件夹下的规则都将被编译进去。

    创建KieContainer

    从类路径下读取文件创建KieContainer ;

    KieServices kieServices = KieServices.Factory.get();
    KieContainer kContainer = kieServices.getKieClasspathContainer();
    
    图片.png

    通过该方式,将所有的java 、kie资源都编译部署到KieContainer中,从而可以在运行时使用之。

    kmodule.file

    KieBase是所有应用程序知识定义的存储库。 它将包含规则,流程,函数和类型模型。 KieBase本身不包含数据;。

    图片.png 图片.png

    KieSession 存储和执行运行时数据。 它从KieBase创建或者当在kmodule.xml中定义时可以直接从KieContainer中创建。

    如下实例, kmodule.xml中可以定义和配置多个KieBase,并且对于每个KieBase都可以创建不同的KieSession 。

    <kmodule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns="http://www.drools.org/xsd/kmodule">
      <configuration>
        <property key="drools.evaluator.supersetOf" value="org.mycompany.SupersetOfEvaluatorDefinition"/>
      </configuration>
      <kbase name="KBase1" default="true" eventProcessingMode="cloud" equalsBehavior="equality" declarativeAgenda="enabled" packages="org.domain.pkg1">
        <ksession name="KSession2_1" type="stateful" default="true"/>
        <ksession name="KSession2_2" type="stateless" default="false" beliefSystem="jtms"/>
      </kbase>
      <kbase name="KBase2" default="false" eventProcessingMode="stream" equalsBehavior="equality" declarativeAgenda="enabled" packages="org.domain.pkg2, org.domain.pkg3" includes="KBase1">
        <ksession name="KSession3_1" type="stateful" default="false" clockType="realtime">
          <fileLogger file="drools.log" threaded="true" interval="10"/>
          <workItemHandlers>
            <workItemHandler name="name" type="org.domain.WorkItemHandler"/>
          </workItemHandlers>
          <listeners>
            <ruleRuntimeEventListener type="org.domain.RuleRuntimeListener"/>
            <agendaEventListener type="org.domain.FirstAgendaListener"/>
            <agendaEventListener type="org.domain.SecondAgendaListener"/>
            <processEventListener type="org.domain.ProcessListener"/>
          </listeners>
        </ksession>
      </kbase>
    </kmodule>
    

    kbase的属性设置:

    Attribute name Default value Admitted values Meaning
    name none any 从KieContainer中获取KieBase的name
    includes none 逗号分隔列表 逗号分隔的列表,kmodule中定义的其他kbase都将包含在该中
    packages all any comma separated list 该packages下所有的资源文件都将包含在该kbase中
    default false true, false 定义该kbase是否是默认的,若是默认的则从KieContainer中可以不传name直接创建,最多只能有一个默认kbase
    equalsBehavior identity identity, equality 定义当新fact插入working memory时drools的行为。 使用identity ,则总是创建一个新的FactHandle,除非同样的对象在workingmemory中不存在。 使用equality ,则只有心插入的对象不同于(根据其提供的equal方法比较)已经存在的fact才创建。
    eventProcessingMode cloud cloud, stream 当以cloud模式创建时,事件被认为是一般的facts。 当stream时允许进行时间推理
    declarativeAgenda disabled disabled, enabled 是否启用Declarative Agenda

    Ksession的属性:

    • name , KIESession的唯一名称标识。用于从KieContainer中获取KieSession。
    • type , stateful、stateless, 默认是stateful ;
    • default , 默认false ;当默认true时, 则允许从KieContainer中不传入name获取。
    • clockType , realtime、pseudo, 默认realtime ; 定义事件时间戳是由系统时钟还是由应用程序控制的伪时钟确定的。 该时钟对于单元测试时间规则特别有用。
    • beliefSystem , simple, jtms, defeasible ; 默认simple ; 定义KieSession使用的信任系统的类型。

    如前例所示, 可以在每个KieSession上声明一个日志记录器,一个或多个WorkItemHandlers,以及3中类型的监听器:ruleRuntimeEventListener, agendaEventListener and processEventListener 。

    在kmodule.xml中声明之后, 既可以使用其name从KieContainer中检索KieBase 和 KieSession。

    如:

    KieServices kieServices = KieServices.Factory.get();
    KieContainer kContainer = kieServices.getKieClasspathContainer();
    
    KieBase kBase1 = kContainer.getKieBase("KBase1");
    KieSession kieSession1 = kContainer.newKieSession("KSession2_1");
    StatelessKieSession kieSession2 = kContainer.newStatelessKieSession("KSession2_2");
    

    需要注意的是,由于KSession2_1和KSession2_2有两种不同的类型(第一种是有状态的,而第二种是无状态的),因此必须根据声明的类型在KieContainer上调用2种不同的方法。 如果向KieContainer请求的KieSession的类型与kmodule.xml文件中声明的类型不对应,则KieContainer将抛出RuntimeException。 此外,由于KieBase和KieSession已被标记为默认值,因此可以从KieContainer获取它们而不传递任何名称。

    KieContainer kContainer = ...
    
    KieBase kBase1 = kContainer.getKieBase(); // returns KBase1
    KieSession kieSession1 = kContainer.newKieSession(); // returns KSession2_1
    

    由于Kie项目也是Maven项目,因此在pom.xml文件中声明的groupId,artifactId和version用于生成在应用程序中唯一标识此项目的ReleaseId。 这允许通过简单地将其ReleaseId传递给KieServices从项目中创建新的KieContainer。

    KieServices kieServices = KieServices.Factory.get();
    ReleaseId releaseId = kieServices.newReleaseId( "org.acme", "myartifact", "1.0" );
    KieContainer kieContainer = kieServices.newKieContainer( releaseId );
    

    使用maven 构建

    Maven的KIE插件可确保工件资源经过验证和预编译。 要使用该插件,只需将其添加到Maven pom.xml,然后packaging使用 kjar。

      <packaging>kjar</packaging>
      ...
      <build>
        <plugins>
          <plugin>
            <groupId>org.kie</groupId>
            <artifactId>kie-maven-plugin</artifactId>
            <version>7.9.0.Final</version>
            <extensions>true</extensions>
          </plugin>
        </plugins>
      </build>
    

    该插件支持所有Drools / jBPM。 但是,如果您在Java类中使用特定的KIE注释,例如@ kie.api.Position,则需要将kie-api的编译时依赖项添加到项目中。 我们建议使用provided scope 添加KIE依赖项。 这样kjar尽可能保持轻量级,并且不依赖于任何特定的KIE版本。

    在没有Maven插件的情况下构建KIE模块会将所有资源按原样复制到生成的JAR中。 当运行时加载JAR时,它将尝试构建所有资源。 如果存在编译问题,它将返回null KieContainer。 它还将编译开销推送到运行时。 通常不建议这样做,并且应始终使用Maven插件。

    通过编程定义KieModule

    支持通过编程的方式定义KieBase 和KieSession , 也支持通过编程将资源动态加载到项目中。 这需要使用KieFileSystem ,它是虚拟文件系统,可以通过它添加任意资源。

    图片.png

    可以通过KieServices获取KieFileSystem 。 kmodule.xml配置文件是必须的一步, kie提供了KieModuleModel来通过编程添加。

    通过KieServices获取KieModuleModel ,配置其KieBases 和 KieSession , 转换为XML , 将XML添加到KieFileSysstem , 如下:

    KieServices kieServices = KieServices.Factory.get();
    KieModuleModel kieModuleModel = kieServices.newKieModuleModel();
    
    KieBaseModel kieBaseModel1 = kieModuleModel.newKieBaseModel( "KBase1 ")
            .setDefault( true )
            .setEqualsBehavior( EqualityBehaviorOption.EQUALITY )
            .setEventProcessingMode( EventProcessingOption.STREAM );
    
    KieSessionModel ksessionModel1 = kieBaseModel1.newKieSessionModel( "KSession1" )
            .setDefault( true )
            .setType( KieSessionModel.KieSessionType.STATEFUL )
            .setClockType( ClockTypeOption.get("realtime") );
    
    KieFileSystem kfs = kieServices.newKieFileSystem();
    kfs.writeKModuleXML(kieModuleModel.toXML());
    

    向KieFileSystem添加其他组件:

    KieFileSystem kfs = ...
    kfs.write( "src/main/resources/KBase1/ruleSet1.drl", stringContainingAValidDRL )
            .write( "src/main/resources/dtable.xls",
                    kieServices.getResources().newInputStreamResource( dtableFileStream ) );
    

    上例显示可以将Kie工件添加为普通String 或 Resource 。 在后一种情况下,资源可以由KieResources工厂创建,也由KieServices提供。 KieResources提供了许多方便的工厂方法,可将InputStream,URL,File或表示文件系统路径的String转换为可由KieFileSystem管理的Resource。


    图片.png

    通常,可以从用于将其添加到KieFileSystem的名称的扩展名推断出资源的类型。 但是,也可以不遵循有关文件扩展名的Kie约定,并明确地将特定的ResourceType分配给资源,如下所示:

    KieFileSystem kfs = ...
    kfs.write( "src/main/resources/myDrl.txt",
               kieServices.getResources().newInputStreamResource( drlStream )
                          .setResourceType(ResourceType.DRL) );
    

    向KieFileSystem中添加resource , 将KieFileSystem传给KieBuilder 来构建之。

    图片.png

    当KieFileSystem的内容被成功构建, 结果KieModule 被自动添加到KieRepository 。 KieRepository 是个单例,是所有KieModule的仓库。

    图片.png

    在此之后,可以通过KieServices使用其ReleaseId为该KieModule创建一个新的KieContainer。 但是,由于在这种情况下KieFileSystem不包含任何pom.xml文件(可以使用KieFileSystem.writePomXML方法添加一个),因此Kie无法确定KieModule的ReleaseId并为其分配默认值。 可以从KieRepository获取此默认ReleaseId,并用于标识KieRepository内部的KieModule。 以下示例显示了整个过程。

    KieServices kieServices = KieServices.Factory.get();
    KieFileSystem kfs = ...
    kieServices.newKieBuilder( kfs ).buildAll();
    KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());
    

    此时,可以从KieContainer中获取KieBases并创建新的KieSession,其方式与直接从类路径创建的KieContainer的方式完全相同。

    检查编译结果是最佳做法。 KieBuilder报告了3种不同严重程度的编译结果:ERROR,WARNING和INFO。 ERROR表示项目的编译失败,没有生成KieModule,没有任何内容会添加到KieRepository。 警告和INFO结果可以忽略,但可供检查。

    KieBuilder kieBuilder = kieServices.newKieBuilder( kfs ).buildAll();
    assertEquals( 0, kieBuilder.getResults().getMessages( Message.Level.ERROR ).size() );
    

    更改构建结果默认严重性

    当添加一个同名的新规则时,默认会替换旧的规则,并打印出INFO结果。这在大多数时候是可以的,但有些情况不希望这么做,需要阻止规则更新并报告error。

    可以通过API调用,系统属性或配置文件来完成。 从此版本开始,Drools支持规则更新和功能更新的可配置结果严重性。 要使用系统属性或配置文件对其进行配置,用户必须使用以下属性:

    // sets the severity of rule updates
    drools.kbuilder.severity.duplicateRule = <INFO|WARNING|ERROR>
    // sets the severity of function updates
    drools.kbuilder.severity.duplicateFunction = <INFO|WARNING|ERROR>
    

    部署 Deploy

    KieBase是所有知识的仓库,包括rule、process、function、type model。
    KieBase本身不包含数据; KieBase可以从包括KieModule的KieContainer中获取。

    图片.png

    有时,如在OSGI环境, KieBase需要使用默认classloader加载不了的类型。 这种情况下,需要使用KieBaseConfiguration 来创建附加classloader 并传递KieContainer给他来创建KieBase。

    KieServices kieServices = KieServices.Factory.get();
    KieBaseConfiguration kbaseConf = kieServices.newKieBaseConfiguration( null, MyType.class.getClassLoader() );
    KieBase kbase = kieContainer.newKieBase( kbaseConf );
    

    KieBase创建并返回KieSession对象,它可以选择保留这些对象的引用。 当KieBase发生修改时,这些修改将应用于会话中的数据。 此引用是弱引用,它也是可选的,由布尔标志控制。

    KieScanner

    KieScanner允许连续监视Maven存储库,以检查是否已安装新版本的Kie项目。 在包装该项目的KieContainer中部署了一个新版本。 使用KieScanner需要kie-ci.jar在类路径上。


    图片.png
    KieServices kieServices = KieServices.Factory.get();
    ReleaseId releaseId = kieServices.newReleaseId( "org.acme", "myartifact", "1.0-SNAPSHOT" );
    KieContainer kContainer = kieServices.newKieContainer( releaseId );
    KieScanner kScanner = kieServices.newKieScanner( kContainer );
    
    // Start the KieScanner polling the Maven repository every 10 seconds
    kScanner.start( 10000L );
    

    在此示例中,KieScanner配置为以固定的时间间隔运行,但也可以通过在其上调用scanNow()方法按需运行它。如果KieScanner在Maven存储库中找到该KieContainer使用的Kie项目的更新版本,它会自动下载新版本并触发新项目的增量构建。此时,KieContainer控制下的现有KieBases和KieSessions将自动升级 - 特别是那些使用getKieBase()获得的KieBases及其相关的KieSession,以及直接使用KieContainer.newKieSession()获得的任何KieSession因此引用默认值KieBase。此外,从现在开始,从KieContainer创建的所有新KieBase和KieSession都将使用新的项目版本。请注意,在KieScanner升级之前通过newKieBase()获得的任何现有KieBase及其任何相关的KieSession都不会自动升级;这是因为通过newKieBase()获得的KieBases不受KieContainer的直接控制。

    如果使用SNAPSHOT,版本范围,LATEST或RELEASE设置,KieScanner将仅对已部署的jar进行拾取更改。固定版本不会在运行时自动更新。

    Maven支持许多机制来管理应用程序中的版本控制和依赖关系。 可以使用特定版本号发布模块,也可以使用SNAPSHOT后缀。 依赖关系可以指定要使用的版本范围,或者采用SNAPSHOT机制的优势。

    StackOverflow为此提供了非常好的描述,如下所示。
    http://stackoverflow.com/questions/30571/how-do-i-tell-maven-to-use-the-latest-version-of-a-dependency

    Runing

    从KieContainer 获取 KieBase

    KieBase kBase = kContainer.getKieBase();
    

    KieSession

    图片.png
    KieSession ksession = kbase.newKieSession();
    

    KieRuntime

    图片.png

    全局Globals与fact不同,他的修改不会触发规则的重新评估。全局变量用户提供静态信息、作为RHS的服务对象,作为规则引擎的返回对象。

    事件模型event model

    事件提供了通知规则引擎的方法, 包括触发规则、声明对象等。 这运行将日志记录审计与应用程序分离。

    KieRuntimeEventManager接口由KieRuntime实现,它提供两个接口,RuleRuntimeEventManager和ProcessEventManager。 我们这里只介绍RuleRuntimeEventManager。


    图片.png

    RuleRuntimeEventManager 支持监听器的添加和删除,因此working memroy 和 agenda的事件可以被监听 :


    图片.png
    ksession.addEventListener( new DefaultAgendaEventListener() {
        public void afterMatchFired(AfterMatchFiredEvent event) {
            super.afterMatchFired( event );
            System.out.println( event );
        }
    });
    

    Drools提供了DebugRuleRuntimeEventListener and DebugAgendaEventListener , 他们实现了打印语句, 使用如下:

    ksession.addEventListener( new DebugRuleRuntimeEventListener() );
    

    所有发出的事件都实现了KieRuntimeEvent接口,该接口可用于检索事件源自的实际KnowlegeRuntime。

    图片.png

    当前支持的事件由:
    The events currently supported are:

    MatchCreatedEvent

    MatchCancelledEvent

    BeforeMatchFiredEvent

    AfterMatchFiredEvent

    AgendaGroupPushedEvent

    AgendaGroupPoppedEvent

    ObjectInsertEvent

    ObjectDeletedEvent

    ObjectUpdatedEvent

    ProcessCompletedEvent

    ProcessNodeLeftEvent

    ProcessNodeTriggeredEvent

    ProcessStartEvent

    KieRuntimeLogger

    图片.png

    KieRuntimeLogger使用Drools中的综合事件系统创建审计日志,该日志可用于记录应用程序的执行,以便以后使用Eclipse审计查看器等工具进行检查。

    KieRuntimeLogger logger =
      KieServices.Factory.get().getLoggers().newFileLogger(ksession, "logdir/mylogfile");
    ...
    logger.close();
    

    Commands and commandExecutor

    KIE拥有有状态或无状态会话的概念。 已经涵盖了使用标准KieRuntime的有状态会话,并且可以随着时间的推移迭代地进行。 Stateless是使用提供的数据集一次性执行KieRuntime。 它可能返回一些结果,会话在最后处理,禁止进一步的迭代交互。

    上述的基础是 CommandExecutor 接口, 有状态和无状态接口都会扩展之。


    图片.png 图片.png

    CommandExecutor允许在这些会话上执行命令,唯一的区别是StatelessKieSession在处理会话之前在结束时执行fireAllRules()。 可以使用CommandExecutor创建命令.Javadocs使用CommandExecutor提供允许的命令的完整列表。

    setGlobal和getGlobal是两个与Drools和jBPM相关的命令。

    在下面设置全局调用setGlobal。 可选的boolean指示命令是否应该返回全局值作为ExecutionResults的一部分。 如果为true,则它使用与全局名称相同的名称。 如果需要替代名称,可以使用String代替布尔值。

    StatelessKieSession ksession = kbase.newStatelessKieSession();
    ExecutionResults bresults =
        ksession.execute( CommandFactory.newSetGlobal( "stilton", new Cheese( "stilton" ), true);
    Cheese stilton = bresults.getValue( "stilton" );
    
    StatelessKieSession ksession = kbase.newStatelessKieSession();
    ExecutionResults bresults =
        ksession.execute( CommandFactory.getGlobal( "stilton" );
    Cheese stilton = bresults.getValue( "stilton" );
    

    上述例子都是使用的单条命令。 组合命令使用BatchExecution 。
    组合命令是个列表, 他迭代每条命令并执行之。 这意味着可以在一个execute()中insert some objects, start a process, call fireAllRules and execute a query。

    StatelessKieSession 会自动在结束时执行fireAllRules() 。

    批处理中具有out标识符集的任何命令都会将其结果添加到返回的ExecutionResults实例。 让我们看一个简单的例子来看看它是如何工作的。 出于说明的目的,所呈现的示例包括来自Drools和jBPM的命令。 它们在Drool和jBPM特定部分中有更详细的介绍。

    StatelessKieSession ksession = kbase.newStatelessKieSession();
    
    List cmds = new ArrayList();
    cmds.add( CommandFactory.newInsertObject( new Cheese( "stilton", 1), "stilton") );
    cmds.add( CommandFactory.newStartProcess( "process cheeses" ) );
    cmds.add( CommandFactory.newQuery( "cheeses" ) );
    ExecutionResults bresults = ksession.execute( CommandFactory.newBatchExecution( cmds ) );
    Cheese stilton = ( Cheese ) bresults.getValue( "stilton" );
    QueryResults qresults = ( QueryResults ) bresults.getValue( "cheeses" );
    

    相关文章

      网友评论

          本文标题:KIE

          本文链接:https://www.haomeiwen.com/subject/xduibftx.html