SeamFramework.orgCommunity Documentation
Seam rends facile l'appel aux règles de bases de JBoss Rules (Drools) depuis les composants Seam ou la définition de processus jBPM.
La première étape est de rendre une instance de org.drools.RuleBase
disponible dans une variable de contexte de Seam. Pour les besoins de tests, Seam fourni un composant livré qui compile un groupe de règles statiques depuis le classpath. Vous pouvez installer ce composant via components.xml
:
<drools:rule-base name="policyPricingRules">
<drools:rule-files>
<value
>policyPricingRules.drl</value>
</drools:rule-files>
</drools:rule-base
>
Ce composant compiles les règles depuis un groupe de fichiers (.drl
) ou d'un fichier de table de décision (.xls
) et met en cache une instance de org.drools.RuleBase
dans le contexte APPLICATION
de Seam. Notez que c'est presque comme cela que vous allez devoir installer les bases de règles multiples dans une application conduite par les règles.
Si vous voulez utiliser un Drools DSL, vous avez aussi besoin de spécifier la définition DSL :
<drools:rule-base name="policyPricingRules" dsl-file="policyPricing.dsl">
<drools:rule-files>
<value
>policyPricingRules.drl</value>
</drools:rule-files>
</drools:rule-base
>
Le support de Drools RuleFlow est aussi disponible et peut vous simplifier l'ajout de .rf
ou de .rfm
comme morceau de vos fichiers de règles comme:
<drools:rule-base name="policyPricingRules" rule-files="policyPricingRules.drl, policyPricingRulesFlow.rf"/>
Notez qu'avec l'utilisation du format Drools 4.x RuleFlow (.rfm
), vous allez avoir besoin de spécifier la propriété système -Ddrools.ruleflow.port=true au démarrage du serveur. Ceci est cependant toujours une fonctionnalité expérimentale et nous conseillons d'utiliser le format Drools5 (.rf
) si possible.
Si vous voulez enregistrer un gestionnaire d'exception de conséquence particulière ay travers de RuleBaseConfiguration, vous allez devoir écrire le gestionnaire, par exemple:
@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() );
}
}
et l'enregistrer:
<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
>
Dans la plus part des applications conduites par les règles, les règles doivent être déployable dynamiquement pour que l'application en production qui veux utiliser un Drools RuleAgent pour gérer la RuleBase. Le RuleAgent peut se connecter au seveur de règle Drools (BRMS) ou aux packages de règles déployés à chauds depuis le référenciel de fichier local. La RuleBase gérant le RulesAgent-managed est aussi configurable dans components.xml
:
<drools:rule-agent name="insuranceRules"
configurationFile="/WEB-INF/deployedrules.properties" />
Le fichier de propriété contient les propriétés spécifiques au RulesAgent. Voici un exemple de fichier de configuration depuis la distribution exemple de 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
Il est aussi possible de configurer les options du composant directement, en outrepassant le fichier de configuration.
<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" />
Ensuite, vous allons avoir besoin de faire une instance de org.drools.WorkingMemory
disponible pour chaque conversation. (Chaque WorkingMemory
accumule les faits relatif à la conversation courante.)
<drools:managed-working-memory name="policyPricingWorkingMemory" auto-create="true" rule-base="#{policyPricingRules}"/>
Notes que nous avons donné au policyPricingWorkingMemory
une référence en retour vers notre base de règles via la propriété de configuration ruleBase
.
Nous pouvons aussi en faire plus pour être informé des évènements du moteur de règles, ce qui inclus le déclenche de règles, le fait que des objets soient injecté, etc. en ajoutant des écouteur d'évènements au 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
>
Nous pouvons injecter notre WorkingMemory
dans tout composant de Seam, insérer des faits, et déclencher des règles:
@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();
}
Nous pouvons même autoriser une base de règle à agir comme un gestionnaire d'action jBPM, un gestionnaire de décision, ou un gestionnaire d'affectation — à la fois dans un enchainement de page ou dans la définition de processus métier.
<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
>
L'élément <assertObjects>
spécifie des expressions EL qui retourne un objet ou une collection d'objjets à insérer dans les faits dans le WorkingMemory
.
L'élément <retractObjects>
d'un autre côté spécifie les expressions EL qui retourne un objet ou une collection d'objets à être extrait depuis le WorkingMemory
.
Il y a aussi le support pour l'utilisation de Drool pour l'affectation des tâches 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
>
Certains objets sont disponibles pour les règles comme Drools globals, dénommé le jBPM Assignable
, comme assignable
et un objet Decision
de Seam, comme décision
. Les règles qui gèrent les décisions devraient s'appeler decision.setOutcome("result")
pour déterminer le résultat de la décision. Les règles qui réalise l'affectation devrait définir l'identifiant de l'acteur en utilisant 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
Vous pouvez trouver beaucoup plus sur les Drools sur http://www.drools.org
Seam vient avec suffisant de dépendances de Drools pour implémenter quelques règles simples. Si vous voulez ajouter des fonctionnalités additionnelles à Drools vous devriez télécharger une distribution complète et ajouter des dépendances additionnelles selon les besoins.