[rules-users] Question about the Nature of Ruleflows
Wolfgang Laun
wolfgang.laun at gmail.com
Wed Aug 22 02:13:54 EDT 2012
@Benjamin:
Esteban just confirms what I was trying to explain in my previous answer.
Ruleflow decisions aren't made on a per-fact basis - all facts in
Working Memory participate in their evaluation.
To activate one or other set of rules, an agenda group might be sufficient;
your "full-fledged example" doesn't really look as if a rule flow is
required.
-W
On 22/08/2012, Esteban Aliverti <esteban.aliverti at gmail.com> wrote:
> Drools Flow (aka JBPM5) will look for all the Persons and Dogs you have in
> your session.
> Since the conditions in an XOR gateway are evaluated in order, the first
> one being true is going to be selected.
> In your case, after you insert the Persons, both rules are activated, but
> the gateway is always going to pick the first one.
> I would suggest to use different process instances for different scenarios.
>
> Best Regards,
>
> XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
>
> Esteban Aliverti
> - Blog @ http://ilesteban.wordpress.com
>
>
> On Tue, Aug 21, 2012 at 11:14 PM, BenjaminWolfe
> <benjamin.e.wolfe at gmail.com>wrote:
>
>> Thanks Wolfgang.
>>
>> My original post was a conceptual analogy. But this still isn't working
>> right for me, so I've written out a full-fledged example to see if you or
>> anyone else can help. The full example is behaving exactly the way my
>> real
>> (important) code is -- which is the wrong way for the business
>> application.
>> :-/ I should add that in real life, the ruleflow groups each have
>> multiple
>> rules within them.
>>
>> So without further ado, here's my code -- two POJOs, a bpmn file, a rule
>> resource, and a test class -- along with the expected output and actual
>> output.
>>
>> *User.java*
>>
>> package com.examples.ruleflow;
>>
>> public class User {
>>
>> private int id;
>>
>> public User() {}
>> public User(int id) {
>> this.id = id;
>> }
>>
>> public int getId() {
>> return id;
>> }
>>
>> public void setId(int id) {
>> this.id = id;
>> }
>> }
>>
>> *Dog.java*
>>
>> package com.examples.ruleflow;
>>
>> public class Dog {
>>
>> private int id;
>> private int ownerId;
>> private boolean hasDogTag;
>>
>> public Dog() {}
>> public Dog(int id) {
>> this.id = id;
>> }
>>
>> public int getId() {
>> return id;
>> }
>> public int getOwnerId() {
>> return ownerId;
>> }
>> public boolean isHasDogTag() {
>> return hasDogTag;
>> }
>> public void setId(int id) {
>> this.id = id;
>> }
>> public void setOwnerId(int ownerId) {
>> this.ownerId = ownerId;
>> }
>> public void setHasDogTag(boolean hasDogTag) {
>> this.hasDogTag = hasDogTag;
>> }
>>
>> }
>>
>> *dog_owner_flow.bpmn*
>>
>> <?xml version="1.0" encoding="UTF-8"?>
>> <definitions id="Definition"
>> targetNamespace="http://www.jboss.org/drools"
>> typeLanguage="http://www.java.com/javaTypes"
>> expressionLanguage="http://www.mvel.org/2.0"
>> xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
>> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>> xsi:schemaLocation="
>> http://www.omg.org/spec/BPMN/20100524/MODEL
>> BPMN20.xsd"
>> xmlns:g="http://www.jboss.org/drools/flow/gpd"
>> xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
>> xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
>> xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
>> xmlns:tns="http://www.jboss.org/drools">
>>
>> <process processType="Private" isExecutable="true"
>> id="com.examples.ruleflow.dogProcess" name="Dog Owner Process"
>> tns:packageName="com.examples.ruleflow" tns:version="1" >
>>
>>
>> <startEvent id="_1" name="StartProcess" />
>> <exclusiveGateway id="_2" name="Gateway" gatewayDirection="Diverging"
>> />
>> <businessRuleTask id="_3" name="Branch A" g:ruleFlowGroup="flowA"
>> ></businessRuleTask>
>> <businessRuleTask id="_4" name="Branch B" g:ruleFlowGroup="flowB"
>> ></businessRuleTask>
>> <exclusiveGateway id="_5" name="Gateway"
>> gatewayDirection="Converging"
>> />
>> <endEvent id="_6" name="End" ><terminateEventDefinition/></endEvent>
>>
>>
>> <sequenceFlow id="_1-_2" sourceRef="_1" targetRef="_2" />
>> <sequenceFlow id="_2-_3" sourceRef="_2" targetRef="_3" name="dog tags
>> OK" tns:priority="1" >
>> <conditionExpression xsi:type="tFormalExpression"
>> language="http://www.jboss.org/drools/rule" >
>> /$u : User()
>> not ( Dog( ownerId == $u.id, hasDogTag == false ) )/
>> </conditionExpression>
>> </sequenceFlow>
>> <sequenceFlow id="_2-_4" sourceRef="_2" targetRef="_4" name="dog tag
>> issue" tns:priority="1" >
>> <conditionExpression xsi:type="tFormalExpression"
>> language="http://www.jboss.org/drools/rule" >
>> /$u : User()
>> exists ( Dog( ownerId == $u.id, hasDogTag == false ) )/
>> </conditionExpression>
>> </sequenceFlow>
>> <sequenceFlow id="_3-_5" sourceRef="_3" targetRef="_5" />
>> <sequenceFlow id="_4-_5" sourceRef="_4" targetRef="_5" />
>> <sequenceFlow id="_5-_6" sourceRef="_5" targetRef="_6" />
>> </process>
>>
>> <bpmndi:BPMNDiagram>
>> <bpmndi:BPMNPlane bpmnElement="com.examples.ruleflow.dogProcess" >
>> <bpmndi:BPMNShape bpmnElement="_1" >
>> <dc:Bounds x="16" y="16" width="48" height="48" />
>> </bpmndi:BPMNShape>
>> <bpmndi:BPMNShape bpmnElement="_2" >
>> <dc:Bounds x="180" y="15" width="48" height="48" />
>> </bpmndi:BPMNShape>
>> <bpmndi:BPMNShape bpmnElement="_3" >
>> <dc:Bounds x="42" y="162" width="80" height="48" />
>> </bpmndi:BPMNShape>
>> <bpmndi:BPMNShape bpmnElement="_4" >
>> <dc:Bounds x="296" y="162" width="80" height="48" />
>> </bpmndi:BPMNShape>
>> <bpmndi:BPMNShape bpmnElement="_5" >
>> <dc:Bounds x="180" y="306" width="48" height="48" />
>> </bpmndi:BPMNShape>
>> <bpmndi:BPMNShape bpmnElement="_6" >
>> <dc:Bounds x="188" y="384" width="48" height="48" />
>> </bpmndi:BPMNShape>
>> <bpmndi:BPMNEdge bpmnElement="_1-_2" >
>> <di:waypoint x="40" y="40" />
>> <di:waypoint x="204" y="39" />
>> </bpmndi:BPMNEdge>
>> <bpmndi:BPMNEdge bpmnElement="_2-_3" >
>> <di:waypoint x="204" y="39" />
>> <di:waypoint x="82" y="186" />
>> </bpmndi:BPMNEdge>
>> <bpmndi:BPMNEdge bpmnElement="_2-_4" >
>> <di:waypoint x="204" y="39" />
>> <di:waypoint x="336" y="186" />
>> </bpmndi:BPMNEdge>
>> <bpmndi:BPMNEdge bpmnElement="_3-_5" >
>> <di:waypoint x="82" y="186" />
>> <di:waypoint x="204" y="330" />
>> </bpmndi:BPMNEdge>
>> <bpmndi:BPMNEdge bpmnElement="_4-_5" >
>> <di:waypoint x="336" y="186" />
>> <di:waypoint x="204" y="330" />
>> </bpmndi:BPMNEdge>
>> <bpmndi:BPMNEdge bpmnElement="_5-_6" >
>> <di:waypoint x="204" y="330" />
>> <di:waypoint x="212" y="408" />
>> </bpmndi:BPMNEdge>
>> </bpmndi:BPMNPlane>
>> </bpmndi:BPMNDiagram>
>> </definitions>
>>
>> *dog_owners.drl*
>>
>> package com.examples.ruleflow
>>
>> rule "sample A"
>> ruleflow-group "flowA"
>> no-loop true
>> dialect "mvel"
>> when
>> $u : User()
>> then
>> System.out.println("User " + $u.id + " took branch A.");
>> end
>>
>> rule "sample B"
>> ruleflow-group "flowB"
>> no-loop true
>> dialect "mvel"
>> when
>> $u : User()
>> then
>> System.out.println("User " + $u.id + " took branch B.");
>> end
>>
>> *DogTest.java*
>>
>> package com.examples.ruleflow;
>>
>> import org.drools.KnowledgeBase;
>> import org.drools.builder.KnowledgeBuilder;
>> import org.drools.builder.KnowledgeBuilderFactory;
>> import org.drools.builder.ResourceType;
>> import org.drools.io.ResourceFactory;
>> import org.drools.logger.KnowledgeRuntimeLogger;
>> import org.drools.logger.KnowledgeRuntimeLoggerFactory;
>> import org.drools.runtime.StatefulKnowledgeSession;
>> /import java.util.List;
>> import java.util.ArrayList;/
>>
>> public class DogTest {
>>
>> public static final void main(String[] args) {
>> try {
>> // load up the knowledge base
>> KnowledgeBase kbase = readKnowledgeBase();
>> StatefulKnowledgeSession ksession =
>> kbase.newStatefulKnowledgeSession();
>> KnowledgeRuntimeLogger logger =
>> KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");
>> /// create and insert facts
>> List<User> users = new ArrayList<User>();
>> List<Dog> dogs = new ArrayList<Dog>();
>>
>> users.add(new User(0));
>> dogs.add(new Dog(0));
>> dogs.get(0).setOwnerId(1);
>> dogs.get(0).setHasDogTag(true);
>> dogs.add(new Dog(1));
>> dogs.get(1).setOwnerId(0);
>> dogs.get(1).setHasDogTag(true);
>>
>> users.add(new User(1));
>> dogs.add(new Dog(2));
>> dogs.get(2).setOwnerId(1);
>> dogs.get(2).setHasDogTag(true);
>> dogs.add(new Dog(3));
>> dogs.get(3).setOwnerId(1);
>> dogs.get(3).setHasDogTag(true);
>> dogs.add(new Dog(4));
>> dogs.get(4).setOwnerId(1);
>> dogs.get(4).setHasDogTag(false);
>>
>> for (User u:users) {
>> ksession.insert(u);
>> }
>> for (Dog d:dogs) {
>> ksession.insert(d);
>> }/
>>
>> // start a new process instance
>> /ksession.startProcess("com.examples.ruleflow.dogProcess");
>> ksession.fireAllRules();/
>> logger.close();
>> } catch (Throwable t) {
>> t.printStackTrace();
>> }
>> }
>>
>> private static KnowledgeBase readKnowledgeBase() throws Exception {
>> KnowledgeBuilder kbuilder =
>> KnowledgeBuilderFactory.newKnowledgeBuilder();
>>
>> /kbuilder.add(ResourceFactory.newClassPathResource("dog_owners.drl"),
>> ResourceType.DRL);
>>
>> kbuilder.add(ResourceFactory.newClassPathResource("dog_owner_flow.bpmn"),
>> ResourceType.BPMN2);/
>> return kbuilder.newKnowledgeBase();
>> }
>> }
>>
>> */Expected/ Console Output...*
>>
>> User /0/ took branch /A/.
>> User /1/ took branch /B/.
>>
>> */Actual/ Console Output...*
>>
>> User /1/ took branch /A/.
>> User /0/ took branch /A/.
>>
>>
>> laune wrote
>> >
>> > On 21/08/2012, BenjaminWolfe <benjamin.e.wolfe@> wrote:
>> >> I'm trying to wrap my mind around the nature of ruleflows -- and I
>> >> think
>> >> this
>> >> question sums up a bit of my confusion.
>> >>
>> >> I have a stateful knowledge session. The stateful knowledge session
>> >> has
>> >> a
>> >> ruleflow associated with it. That ruleflow diverges into two branches
>> --
>> >> branch A and branch B -- based on a rule constraint. It's an XOR, and
>> >> the
>> >> mvel rule constraints are something like this:
>> >>
>> >> to branch A
>> >> $u : User( $i : userId )
>> >> exists ( Dog( owner == $i, hasDogTag == false) )
>> >>
>> >> to branch B
>> >> $u : User( $i : userId )
>> >> not ( Dog( owner == $i, hasDogTag == false) )
>> >>
>> >> Then the two branches converge again. I insert two facts: user 1,
>> >> whose
>> >> dogs all have dog tags, and user 2 whose third dog is missing a tag.
>> >> Then,
>> >> after I insert both facts, I fire all rules.
>> >
>> > If you don't insert any Dogs, only the condition for branch B is true,
>> > since there no Dogs at all, tag or no tag.
>> >
>> > If you insert Dogs according to your statement, both conditions are
>> > true, A for user 2 and B for user 1 (which is not what you describe
>> > below, but I think this is an oversight).
>> >
>> > Anyway, a "flow" will not cycle automatically if there are several
>> > fact groups, with some of them requiring this or that processing. To
>> > notify Users with untagged dogs, a simple rule with the conditions
>> > you've posted and with a consequence notifying the user would be
>> > sufficient.
>> >
>> > For an overall decision between "there are tagless dogs" and "all dogs
>> > are tagged" you'd need conditions like these:
>> >
>> > exists( Dog( hasDogTag == false) )
>> >
>> > not( Dog( hasDogTag == false) )
>> >
>> > -W
>> >
>> >
>> >>
>> >> Should the flow be like this?
>> >>
>> >> user 1: start --> diverge --> branch A (tell him to buy dog tags) -->
>> >> converge --> end
>> >> user 2: start --> diverge --> branch B (leave him alone) --> converge
>> -->
>> >> end
>> >>
>> >> Or does a ruleflow look at the whole session rather than each fact --
>> >> in
>> >> which case either both users would pass through branch A, or both
>> >> would
>> >> pass
>> >> through branch B?
>> >>
>> >> If I want the first case to happen, is there something I'm missing in
>> the
>> >> implementation? And are there any more details I can add to make my
>> post
>> >> more specific? Thank you for your help.
>> >>
>> >>
>> >>
>> >> --
>> >> View this message in context:
>> >>
>> http://drools.46999.n3.nabble.com/Question-about-the-Nature-of-Ruleflows-tp4019292.html
>> >> Sent from the Drools: User forum mailing list archive at Nabble.com.
>> >> _______________________________________________
>> >> rules-users mailing list
>> >> rules-users at .jboss
>> >> https://lists.jboss.org/mailman/listinfo/rules-users
>> >>
>> > _______________________________________________
>> > rules-users mailing list
>> > rules-users at .jboss
>> > https://lists.jboss.org/mailman/listinfo/rules-users
>> >
>>
>>
>>
>> --
>> View this message in context:
>> http://drools.46999.n3.nabble.com/Question-about-the-Nature-of-Ruleflows-tp4019292p4019325.html
>> Sent from the Drools: User forum mailing list archive at Nabble.com.
>> _______________________________________________
>> rules-users mailing list
>> rules-users at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/rules-users
>>
>
More information about the rules-users
mailing list