[rules-users] determining what field changed
Is it possible to determine what fields from an object changed within a rule. So I am using this to determine if any DataObject has changed: //IDENTIFY ANY DATAOBJECT CHANGES rule identify any DATAOBJECT when $do : DataObject(); then System.err.println(ANY DataObject change detected: + $do); End However this also fires when any new DataObject() is injected into the system and the rules are fired. I would like to be able to only have a rule fire when an object is first created Vs. when it is modified and is there a way to detect what values of an object have changed if I don't explicitly know what fields of DataObject changed ahead of time? Thanks, Chris ___ rules-users mailing list rules-users@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-users
Re: [rules-users] determining what field changed
Not really. Without modifying the objects you could do this outside the rules using a WorkingMemoryEventListener, which has objectInserted() and objectUpdated() methods. Event if you can modify the DataObject to add an I'm a new object flag, and set it immediately on insertion, then you could do differentiate with two rules: rule identify new DATAOBJECT when do : DataObject(n00b == true); then do.setN00b(false); update(do); System.err.println(DataObject assertion detected: + do); end rule identify modified DATAOBJECT when do : DataObject(n00b == false); then System.err.println(DataObject modification detected: + do); end Which would still catch a spurious modification notification on assert! At that point the semi-risky alternative is to not call update() in the identify new DATAOBJECT rule action. That way, the identify modified DATAOBJECT is not immediately activated, but it would be activated the next time update() is called on the object. I say semi-risky because it's not often a good idea to put a WM object into a state that the rete is not aware of, but in this case it would do what you want. --- On Wed, 9/16/09, Chris Richmond crichm...@referentia.com wrote: From: Chris Richmond crichm...@referentia.com Subject: [rules-users] determining what field changed To: 'Rules Users List' rules-users@lists.jboss.org Date: Wednesday, September 16, 2009, 2:41 PM Is it possible to determine what fields from an object changed within a rule. So I am using this to determine if any DataObject has changed: //IDENTIFY ANY DATAOBJECT CHANGES rule identify any DATAOBJECT when $do : DataObject(); then System.err.println(ANY DataObject change detected: + $do); End However this also fires when any new DataObject() is injected into the system and the rules are fired. I would like to be able to only have a rule fire when an object is first created Vs. when it is modified and is there a way to detect what values of an object have changed if I don’t explicitly know what fields of DataObject changed ahead of time? Thanks, Chris -Inline Attachment Follows- ___ rules-users mailing list rules-users@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-users ___ rules-users mailing list rules-users@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-users
Re: [rules-users] determining what field changed
In general do you have any suggestions for getting around multiple update detects being made? In other words I have a rule to detect if my DataObject has fieldA X and if so, then modify fieldB. Then another rule that checks if fieldB = value and then updates field C. So something like: rule identify modified DATAOBJECT when do : DataObject(FieldA x); then modify(do.fieldB = value) end So something like: rule identify modified DATAOBJECT when do : DataObject(fieldB == value); then modify(do.fieldC = someValue) end rule identify modified DATAOBJECT when do : DataObject(fieldC == someValToMatchForC); then modify(do.fieldA = someNewValueForA) end But of course this leads to some sort of cross product execution as each one is run all over again after another makes a change and ramps out of control One question. I have been using modify() and I notice you had explicit: do.setN00b(false); update(do); What is the difference and will that matter to my scenario? Thanks, Chris -Original Message- From: rules-users-boun...@lists.jboss.org [mailto:rules-users-boun...@lists.jboss.org] On Behalf Of Greg Barton Sent: Wednesday, September 16, 2009 10:14 AM To: Rules Users List Subject: Re: [rules-users] determining what field changed Not really. Without modifying the objects you could do this outside the rules using a WorkingMemoryEventListener, which has objectInserted() and objectUpdated() methods. Event if you can modify the DataObject to add an I'm a new object flag, and set it immediately on insertion, then you could do differentiate with two rules: rule identify new DATAOBJECT when do : DataObject(n00b == true); then do.setN00b(false); update(do); System.err.println(DataObject assertion detected: + do); end rule identify modified DATAOBJECT when do : DataObject(n00b == false); then System.err.println(DataObject modification detected: + do); end Which would still catch a spurious modification notification on assert! At that point the semi-risky alternative is to not call update() in the identify new DATAOBJECT rule action. That way, the identify modified DATAOBJECT is not immediately activated, but it would be activated the next time update() is called on the object. I say semi-risky because it's not often a good idea to put a WM object into a state that the rete is not aware of, but in this case it would do what you want. --- On Wed, 9/16/09, Chris Richmond crichm...@referentia.com wrote: From: Chris Richmond crichm...@referentia.com Subject: [rules-users] determining what field changed To: 'Rules Users List' rules-users@lists.jboss.org Date: Wednesday, September 16, 2009, 2:41 PM Is it possible to determine what fields from an object changed within a rule. So I am using this to determine if any DataObject has changed: //IDENTIFY ANY DATAOBJECT CHANGES rule identify any DATAOBJECT when $do : DataObject(); then System.err.println(ANY DataObject change detected: + $do); End However this also fires when any new DataObject() is injected into the system and the rules are fired. I would like to be able to only have a rule fire when an object is first created Vs. when it is modified and is there a way to detect what values of an object have changed if I dont explicitly know what fields of DataObject changed ahead of time? Thanks, Chris -Inline Attachment Follows- ___ rules-users mailing list rules-users@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-users ___ rules-users mailing list rules-users@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-users ___ rules-users mailing list rules-users@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-users
Re: [rules-users] determining what field changed
There is no functional difference between modify and update. update is the new syntax. See section 3.3.3.1.3 of the expert doc: https://hudson.jboss.org/hudson/job/drools/lastSuccessfulBuild/artifact/trunk/target/docs/drools-expert/html_single/index.html#d0e1264 (scroll down a bit) As for general suggestions to prevent rule re-firing, there are several options. The most general is make your conditions the negation of your action. In other words, the conditions say the objects are in state A, and not in state B yet and state B is what you do to them in the action. So, to modify your example: rule Rule1 when do : DataObject(FieldA x, fieldB != value); then modify(do.fieldB = value) end So something like: rule Rule2 when do : DataObject(fieldB == value, fieldC != someValue); then modify(do.fieldC = someValue) end rule Rule3 when do : DataObject(fieldC == someValToMatchForC, do.fieldA != someNewValueForA); then modify(do.fieldA = someNewValueForA) end So you're always telling the engine to fire the rule if the objects are in some state, and NOT in the state you're about to put them in. Another general pattern is to have the objects hold some artificial state (or match them with an object that holds the artificial state) that restricts rule firing to transitions in a certain logical path. One simple way to do this is to have a String (or preferably an Enum) value in the object that informs the rules what artificial state the object is in. rule Rule1 when do : DataObject(FieldA x, state == StageA); then do.setFieldB(value); do.setStage(StageB); update(do); end So something like: rule Rule2 when do : DataObject(fieldB == value, state == StageB); then do.setFieldC(someValue) do.setStage(StageC); update(do); end rule Rule3 when do : DataObject(fieldC == someValToMatchForC, state == StageC); then do.setFieldA(someNewValueForA); do.setStage(StageD); update(do); end This isn't as restrictive as you might think. There are also the flow control mechanisms available for rule flow and agenda grouping, but they don't reach down to the object level. However, mattering on how many conflicting objects you have in memory at once, they can be quite useful for this purpose as well. (Basically, you force the entire engine into limited processing states, instead of individual objects.) --- On Wed, 9/16/09, Chris Richmond crichm...@referentia.com wrote: From: Chris Richmond crichm...@referentia.com Subject: Re: [rules-users] determining what field changed To: 'Rules Users List' rules-users@lists.jboss.org Date: Wednesday, September 16, 2009, 3:52 PM In general do you have any suggestions for getting around multiple update detects being made? In other words I have a rule to detect if my DataObject has fieldA X and if so, then modify fieldB. Then another rule that checks if fieldB = value and then updates field C. So something like: rule identify modified DATAOBJECT when do : DataObject(FieldA x); then modify(do.fieldB = value) end So something like: rule identify modified DATAOBJECT when do : DataObject(fieldB == value); then modify(do.fieldC = someValue) end rule identify modified DATAOBJECT when do : DataObject(fieldC == someValToMatchForC); then modify(do.fieldA = someNewValueForA) end But of course this leads to some sort of cross product execution as each one is run all over again after another makes a change and ramps out of control One question. I have been using modify() and I notice you had explicit: do.setN00b(false); update(do); What is the difference and will that matter to my scenario? Thanks, Chris -Original Message- From: rules-users-boun...@lists.jboss.org [mailto:rules-users-boun...@lists.jboss.org] On Behalf Of Greg Barton Sent: Wednesday, September 16, 2009 10:14 AM To: Rules Users List Subject: Re: [rules-users] determining what field changed Not really. Without modifying the objects you could do this outside the rules using a WorkingMemoryEventListener, which has objectInserted() and objectUpdated() methods. Event if you can modify the DataObject to add an I'm a new object flag, and set it immediately on insertion, then you could do differentiate with two rules: rule identify new DATAOBJECT when do : DataObject(n00b == true); then do.setN00b(false); update(do); System.err.println(DataObject assertion detected: + do); end rule identify modified DATAOBJECT when do : DataObject(n00b == false); then System.err.println(DataObject modification detected: + do); end Which would still catch a spurious modification notification on assert! At that point the semi-risky alternative is to not call update() in the identify new DATAOBJECT rule action. That way