SeamFramework.orgCommunity Documentation

Capitolo 14. Seam e JBoss Rules

14.1. Installazione delle regole
14.2. Utilizzo delle regole da un componente SEAM
14.3. Utilizzo delle regole da una definizione di processo jBPM

Seam facilita le chiamate alle regole di JBoss Rules (Drools) dai componenti Seam o dalle definizioni di processo jBPM.

Il primo passo è creare un'istanza di org.drools.RuleBase disponibile in una variabile del contesto di Seam. Per i test Seam fornisce un componente interno che compila un set statico di regole dal classpath. Si può installare questo componente tramite components.xml:


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

Questo componente compila le regole da un set di file .drl e mette in cache un'istanza di org.drools.RuleBase nel contesto APPLICATION di Seam. Notare che è abbastanza probabile che in un'applicazione guidata dalle regole occorra installare altre basi di regole.

Se si vuole utilizzare una Drool DSL, devi specificare la definizione DSL:


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

Nella maggior parte delle applicazioni guidate dalle regole, le regole devono essere dinamicamente deployabili, e quindi un'applicazione in produzione dovrà usare un Drools RuleAgent per gestire la RuleBase. Il RuleAgent può connettersi al server di regole Drool (BRMS) od eseguire l'hot deploy dei pacchetti di regole dal repository locale. La RuleBase gestita dal RulesAgen è configurabile in components.xml:


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

Il file delle proprietà contiene proprietà specifiche per RulesAgent. Ecco un file di configurazione d'esempio proveniente dalla distribuzione 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

E' anche possibile configurare le opzioni derettamente sul componente, bypassando il file di configurazione.


<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" />

Successivamente occorre rendere disponibile ad ogni conversazione un'istanza di org.drools.WorkingMemory. (Ogni WorkingMemory accumula fatti relativi alla conversazione corrente.)


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

Notare che è stato dato a policyPricingWorkingMemory un riferimento alla base di regole tramite la proprietà di configurazione ruleBase.

Ora è possibile iniettare la WorkingMemory in un qualsiasi componente di Seam, asserire i fatti e lanciare le regole:

@In WorkingMemory policyPricingWorkingMemory;


@In Policy policy;
@In Customer customer;
public void pricePolicy() throws FactException
{
    policyPricingWorkingMemory.assertObject(policy);
    policyPricingWorkingMemory.assertObject(customer);
    policyPricingWorkingMemory.fireAllRules();
}

Si può anche consentire alla base di regole di agire come action handler di jBPM, decision handler, o assignment handler — sia in una definizione di pageflow sia in un processo di business.


<decision name="approval">
         
    <handler class="org.jboss.seam.drools.DroolsDecisionHandler">
        <workingMemoryName
>orderApprovalRulesWorkingMemory</workingMemoryName>
        <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
>

L'elemento <assertObjects> specifica le espressioni EL che restituiscono un oggetto od una collezione di oggetti da asserire come fatti nella WorkingMemory.

Esiste anche il supporto per l'uso di Drools per le assegnazioni dei task in jBPM:


<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
>

Alcuni oggetti sono consultabili dalle regole come Drools globals, chiamate Assignable in jBPM, come assignable ed oggetto Decision in Seam, come decision. Le regole che gestiscono le decisioni dovrebbero chiamare decision.setOutcome("result") per determinare il risultato della decisione. Le regole che eseguono assegnazioni dovrebbero impostare l'actor id usando Assignable.

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

Attenzione

Seam viene fornito con dipendenze Drools sufficienti per implementare alcune regole semplici. Per aggiungere ulteriori funzionalità a Drools occorre scaricare la distribuzione completa ed aggiungere le dipendenze necessarie.

Suggerimento

Drools viene rilasciato con MVEL compilato per Java 1.4, che è compatibile con Java 1.4, Java 5 e Java 6. E' possibile cambiare il jar MVEL con quello compilato per la propria versione di Java.