SeamFramework.orgCommunity Documentation

第14章 Seam と JBoss Rules

14.1. ルールをインストールする
14.2. Seam コンポーネントからのルールを使用する
14.3. jBPM プロセス定義からのルールを使用する

Seam では、Seam コンポーネントあるいは jBPM プロセス定義から JBoss Rules (Drools) の RuleBase を容易に呼び出せます。

最初のステップは、Seam コンテキスト変数で org.drools.RuleBase のインスタンスを使用可能にすることです。 テスト目的で、Seam はクラスパスから静的なルール一式をコンパイルする組み込みコンポーネントを提供しています。 このコンポーネントは components.xml を使ってインストールすることができます。


<drools:rule-base name="policyPricingRules">
    <drools:rule-files>
        <value
>policyPricingRules.drl</value>
    </drools:rule-files>
</drools:rule-base
>

This component compiles rules from a set of DRL (.drl) or decision table (.xls) files and caches an instance of org.drools.RuleBase in the Seam APPLICATION context. Note that it is quite likely that you will need to install multiple rule bases in a rule-driven application.

Drools DSLを利用するのであれば DSL 定義も指定しなければなりません。


<drools:rule-base name="policyPricingRules" dsl-file="policyPricing.dsl">
    <drools:rule-files>
        <value
>policyPricingRules.drl</value>
    </drools:rule-files>
</drools:rule-base
>

Support for Drools RuleFlow is also available and you can simply add a .rf or a .rfm as part of your rule files as:



        <drools:rule-base name="policyPricingRules" rule-files="policyPricingRules.drl, policyPricingRulesFlow.rf"/>
        

Note that when using the Drools 4.x RuleFlow (.rfm) format, you need to specify the -Ddrools.ruleflow.port=true system property on server startup. This is however still an experimental feature and we advise to use the Drools5 (.rf) format if possible.

If you want to register a custom consequence exception handler through the RuleBaseConfiguration, you need to write the handler, for example:

@Scope(ScopeType.APPLICATION)

@Startup
@Name("myConsequenceExceptionHandler")
public class MyConsequenceExceptionHandler implements ConsequenceExceptionHandler, Externalizable {
   public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
   }
   public void writeExternal(ObjectOutput out) throws IOException {
   }
   public void handleException(Activation activation,
                               WorkingMemory workingMemory,
                               Exception exception) {
       throw new ConsequenceException( exception,
                                       activation.getRule() );
   }
}

and register it:


<drools:rule-base name="policyPricingRules" dsl-file="policyPricing.dsl" consequence-exception-handler="#{myConsequenceExceptionHandler}">
    <drools:rule-files>
        <value>policyPricingRules.drl</value>
    </drools:rule-files>
</drools:rule-base>

ほとんどのルール型アプリケーションでは、 ルールが動的にデプロイ可能である必要があるので実稼働アプリケーションは RuleBase の管理に Drools RuleAgent の使用を好みます。 RuleAgent は Drools ルールサーバー (BRMS) またはローカルファイルレポジトリにあるホットデプロイルールのパッケージに接続することができます。 RulesAgent 管理の RuleBase も components.xml で設定が可能です。


<drools:rule-agent name="insuranceRules" 
                    configurationFile="/WEB-INF/deployedrules.properties" />

プロパティファイルはその RulesAgent に固有のプロパティを含んでいます。 Drools サンプルディストリビューションからの設定ファイルの例を示します。

newInstance=true
url=http://localhost:8080/drools-jbrms/org.drools.brms.JBRMS/package/org.acme.insurance/fmeyer
localCacheDir=/Users/fernandomeyer/projects/jbossrules/drools-examples/drools-examples-brms/cache
poll=30
name=insuranceconfig

また、 設定ファイルを避けコンポーネントで直接オプションを設定することも可能です。


<drools:rule-agent name="insuranceRules"
   url="http://localhost:8080/drools-jbrms/org.drools.brms.JBRMS/package/org.acme.insurance/fmeyer"
   local-cache-dir="/Users/fernandomeyer/projects/jbossrules/drools-examples/drools-examples-brms/cache"
   poll="30"
   configuration-name="insuranceconfig" />

次に、各対話に対して org.drools.WorkingMemory インスタンスを有効化する必要があります。 (各 WorkingMemory は、現在の対話に関連する fact を蓄積します。)


<drools:managed-working-memory name="policyPricingWorkingMemory" auto-create="true" rule-base="#{policyPricingRules}"/>

policyPricingWorkingMemory に、 ruleBase 設定プロパティにより、 RuleBase への参照を与えていることに留意してください。

We can also add means to be notified of rule engine events, including rules firing, objects being asserted, etc. by adding event listeners to WorkingMemory.


<drools:managed-working-memory name="policyPricingWorkingMemory" auto-create="true" rule-base="#{policyPricingRules}">
        <drools:event-listeners>
            <value>org.drools.event.DebugWorkingMemoryEventListener</value>
        <value>org.drools.event.DebugAgendaEventListener</value>
        </drools:event-listeners>
</drools:managed-working-memory>

WorkingMemory を、 任意の Seam コンポーネントにインジェクトし、 fact をアサートし、そしてルールを実行することができます。

@In WorkingMemory policyPricingWorkingMemory;


@In Policy policy;
@In Customer customer;
public void pricePolicy() throws FactException
{
        policyPricingWorkingMemory.insert(policy);
        policyPricingWorkingMemory.insert(customer); 
        // if we have a ruleflow, start the process
        policyPricingWorkingMemory.startProcess(startProcessId)
    policyPricingWorkingMemory.fireAllRules();
}

You can even allow a rule base to act as a jBPM action handler, decision handler, or assignment handler — in either a pageflow or business process definition.


<decision name="approval">
         
    <handler class="org.jboss.seam.drools.DroolsDecisionHandler">
        <workingMemoryName>orderApprovalRulesWorkingMemory</workingMemoryName>
        <!-- if a ruleflow was added -->
        <startProcessId>approvalruleflowid</startProcessId>
        <assertObjects>
            <element>#{customer}</element>
            <element>#{order}</element>
            <element>#{order.lineItems}</element>
        </assertObjects>
    </handler>
    
    <transition name="approved" to="ship">
        <action class="org.jboss.seam.drools.DroolsActionHandler">
            <workingMemoryName>shippingRulesWorkingMemory</workingMemoryName>
            <assertObjects>
                <element>#{customer}</element>
                <element>#{order}</element>
                <element>#{order.lineItems}</element>
            </assertObjects>
        </action>
    </transition>
    
    <transition name="rejected" to="cancelled"/>
    
</decision>

<assertObjects> エレメントは WorkingMemory に fact としてアサートされるオブジェクトの集合または 1 オブジェクトを返す EL 式を指定します。

The <retractObjects> element on the other hand specifies EL expressions that return an object or collection of objects to be retracted from the WorkingMemory.

jBPM タスク割り当てのために Drools の使用もサポートしています。


<task-node name="review">
    <task name="review" description="Review Order">
        <assignment handler="org.jboss.seam.drools.DroolsAssignmentHandler">
            <workingMemoryName
>orderApprovalRulesWorkingMemory</workingMemoryName>
            <assertObjects>
                <element
>#{actor}</element>
                <element
>#{customer}</element>
                <element
>#{order}</element>
                <element
>#{order.lineItems}</element>
            </assertObjects>
        </assignment>
    </task>
    <transition name="rejected" to="cancelled"/>
    <transition name="approved" to="approved"/>
</task-node
>

ルールに対して特定のオブジェクトが Drools のグローバルとして使用可能です。 jBPM Assignableassignable として、 Seam Decision オブジェクトは decision として使用可能です。 decision を処理するルールは decision.setOutcome"result") を呼び出して決定結果を確定します。 assignment を実行するルールは Assignable を使ってそのアクターIDを設定するはずです。

package org.jboss.seam.examples.shop

import org.jboss.seam.drools.Decision

global Decision decision

rule "Approve Order For Loyal Customer"
  when
    Customer( loyaltyStatus == "GOLD" )
    Order( totalAmount <= 10000 )
  then
    decision.setOutcome("approved");
end
package org.jboss.seam.examples.shop

import org.jbpm.taskmgmt.exe.Assignable

global Assignable assignable

rule "Assign Review For Small Order"
  when
    Order( totalAmount <= 100 )
  then
    assignable.setPooledActors( new String[] {"reviewers"} );
end

注意

Seam はシンプルなルールを実装するのには十分な Drools の依存性を同梱しています。 Drools に機能を追加したい場合は完全なディストリビューションをダウンロードしてから必要に応じて追加の依存性を追加してください。