1

プラグインをインストールせずに GRAILS3 で drools ルール エンジンを使用することは可能ですか? drools が Java に実装されており 、Ken Siprell による GRAILS 用の実際の公式プラグインが (どうやら) 機能していないことを知っているためです。

4

1 に答える 1

2

多くの調査と試行錯誤の結果、プラグインなしで DROOLS エンジンを使用してデータを処理できる小さな GRAILS3 API サービスを手に入れました。DROOLS が Java に基づいており、GRAILS と Java の完全な互換性があるため、これが可能です。
必要なものは次のとおりです。

  1. build.gradle に最小限の DROOLS 依存関係を含める
  2. files.drl を保存するフォルダーを選択します
  3. 処理するファクトとして使用するいくつかのエンティティがあります (それらを永続化することは必須ではないため、休止状態の構成はスキップします)
  4. ルールベースの知識を構築し、セッションを取得するためのサービスを実装する
  5. DROOLS を介してデータを処理するためのいくつかのメソッドを API コントローラーに実装します (サービスからセッションを取得)。

以下に、そのすべての簡単な例を示します。

DROOLS の依存関係 (build.gradle 内):

runtime "org.drools:drools-compiler:6.5.0.Final"
compile "org.drools:drools-core:6.5.0.Final"
compile "org.drools:knowledge-api:6.5.0.Final"

src/rules の DRL ストレージ (このパスへの参照はサービスにあります。以下を参照してください): myrules.drl

import my.entities.Book;
import java.util.List;

rule "Find author"
   salience 10
   when
    $book: Book( author=="Shakespeare" )
   then
    System.out.println("Book found, date:"+$book.getDate0());
end

Book などのエンティティ:

package my.entities
import java.util.Date

class Book {
    String title, author
    Date date0
}

DROOLS の知識を構築し、セッションを取得するためのサービス (ステートフル エンジンより軽いステートレス エンジンを用意しました):

package my.services
import grails.converters.*

import org.kie.api.runtime.*;
import org.kie.internal.io.ResourceFactory;
import org.kie.api.*;
import org.kie.api.io.*;
import org.kie.api.builder.*;

class DroolsService  {

def getSession() {
        def path    = "src/rules"
        def lru = ["myrules.drl"]
        def rules   = []
        lru.each{
            rules.add("${path}${it}")
        }
        StatelessKieSession ksess   = buildSession(rules)
        return ksess
    }
}

private buildSession(def lfile) {
    println "Building DROOLS session..."
    try {
        def lres    = []
        lfile.each{
            Resource resource   = ResourceFactory.newFileResource(new File(it));
            lres.add(resource)
        }

        KieContainer kieContainer = buildKieContainer(lres)
        StatelessKieSession kieSession = kieContainer.newStatelessKieSession()
        return kieSession
    } catch(Exception e) {
        e.printStackTrace()
        return null
    }

protected KieContainer buildKieContainer(def lres) {
    KieServices kieServices = KieServices.Factory.get()
    KieFileSystem kieFileSystem = kieServices.newKieFileSystem()
    lres.each{
        kieFileSystem.write("src/main/resources/rule.drl", it)  
    }

    KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem).buildAll()
    Results results = kieBuilder.results
    if (results.hasMessages(Message.Level.ERROR)) {
        throw new IllegalStateException(this.class.name + ": " + results.messages.toString())
    }
    KieContainer kieContainer = kieServices.newKieContainer(kieServices.repository.defaultReleaseId)
    kieContainer
}

}

APIコントローラーでのサービスの使用:

class ApiController  {

def droolsService

def proc = {
    def sess    = droolsService.getSession()

    def mess    = "ok DROOLS proc from JSON"
    Book book   = null

    if (params.contbook) {
        book = new Book(JSON.parse(params.contbook))
        sess.execute book
    } 

    response.status  = 200 
    render mess
}

コントローラーでは、DROOLS サービスによって初期化されたルール エンジンで実行するために、パラメーターから json データを取得し、それらによってエンティティを設定します。もちろん、これは非常に単純な解決策ですが、機能しています。

いくつかのメモ:

  • 各 drl ルールの RHS 部分 (「then」の後) は Java でなければならないため、例のように、エンティティのプライベート プロパティに直接アクセスすることはできませんが、getter または setter (GRAILS によって暗黙的に作成されます) を使用する必要があります。
  • getSession はナレッジの新しいビルドと新しいセッションを作成しますが、これは最適ではありません。DROOLS セッションを保存するために再設計し、ユーザー セッションで再利用することができます。
  • 複数の files.drl を同じフォルダーに入れることができ、ナレッジ エンジンにそれらをパックするために、それらをすべてサービスにリストする必要があります。

それがすべて役立つことを願っています。

于 2016-11-11T15:49:28.930 に答える