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