[rules-users] Fire rule only upon change of particular event (or fact)
Jörg Henne
hennejg at gmail.com
Sun May 26 07:27:38 EDT 2013
Hi all,
after using drools for some time now, I have repeatedly stumbled upon
situations where it would have been useful to be able to tell Drools to fire
a rule only upon the insertion of a particular event, but not other
events/facts on which the rule depends. It might be that I am hopelessly
mis-guided, but I would like to float an idea and see what you think.
To illustrate what I am talking about, please consider the following rules:
------------------------------------------------------------------------------------------------------------
package test
declare SomeEvent
@role(event)
name: String
end
declare SomeFact
@role(fact)
name: String
end
rule "Trigger on some event when there is some fact"
when
e: SomeEvent()
f: SomeFact()
then
System.out.println("=> Got Event '" + e.getName() + "' and Fact '" +
f.getName() + "'");
end
rule "Discard 'used' events"
salience -99999
when
e: SomeEvent()
then
retract(e);
end
------------------------------------------------------------------------------------------------------------
Now we insert facts and events, for example like this
------------------------------------------------------------------------------------------------------------
rule "Insert fact"
when
then
System.out.println("Inserting initial Fact");
insert(new SomeFact("initial fact"));
end
rule "Insert an event"
timer(int: 5s)
when
then
System.out.println("Inserting initial Event");
insert(new SomeEvent("initial event"));
end
rule "Insert yet another fact"
timer(int: 10s)
when
then
System.out.println("Inserting yet another fact");
insert(new SomeFact("yet another"));
end
rule "Insert yet another event"
timer(int: 10s)
when
then
System.out.println("Inserting yet another event");
insert(new SomeEvent("yet another"));
end
------------------------------------------------------------------------------------------------------------
The result of running those rules is, of course:
------------------------------------------------------------------------------------------------------------
Inserting initial Fact
Inserting initial Event
=> Got Event 'initial event' and Fact 'initial fact'
Inserting yet another fact
=> Got Event 'initial event' and Fact 'yet another'
Inserting yet another event
=> Got Event 'yet another' and Fact 'yet another'
=> Got Event 'yet another' and Fact 'initial fact'
------------------------------------------------------------------------------------------------------------
Please note the output does not match the name of the rule "Trigger on some
event when there is some fact". In fact, this rule fires irrespective of
whether an event is inserted or a fact. But what I really want is, that it
just fires upon the 'arrival' of events. A possible syntax extension whould
be something along the lines of:
------------------------------------------------------------------------------------------------------------
rule "Trigger on some event when there is some fact"
when
upon(e: SomeEvent())
f: SomeFact()
then
System.out.println("=> Got Event '" + e.getName() + "' and Fact '" +
f.getName() + "'");
end
------------------------------------------------------------------------------------------------------------
The expected output of that would be:
------------------------------------------------------------------------------------------------------------
Inserting initial Fact
Inserting initial Event
=> Got Event 'initial event' and Fact 'initial fact'
Inserting yet another fact
Inserting yet another event
=> Got Event 'yet another' and Fact 'yet another'
=> Got Event 'yet another' and Fact 'initial fact'
------------------------------------------------------------------------------------------------------------
There are work-arounds that let me achieve the desired behaviour, for
example this one:
------------------------------------------------------------------------------------------------------------
rule "Focus on 'process SomeEvent'"
agenda-group "process SomeEvent"
auto-focus
when
e: SomeEvent()
then
// nothing to do but focus the agenda-group
end
rule "Trigger on some event when there is some fact"
agenda-group "process SomeEvent"
when
e: SomeEvent()
f: SomeFact()
then
System.out.println("=> Got Event '" + e.getName() + "' and Fact '" +
f.getName() + "'");
end
------------------------------------------------------------------------------------------------------------
However, I think the hypothetical 'upon'-keyword would be a lot clearer. Is
there any fundamental reason (e.g. rooted in the rete-algorithm or the way
Drools implements it) that would preclude the implementation of 'upon'? And,
more importantly, do you even agree with me that it would be a useful
extension?
Please note that while I always spoke of events in conjunction with 'upon' I
don't see a reason why it should not behave this way with plain facts as
well. Please not as well that the inverse of upon would also be conceivable:
"don't fire this rule just because <some pattern> triggered", e.g. maybe
simply "not(upon(Pattern()))".
Thanks
Joerg Henne
--
View this message in context: http://drools.46999.n3.nabble.com/Fire-rule-only-upon-change-of-particular-event-or-fact-tp4023972.html
Sent from the Drools: User forum mailing list archive at Nabble.com.
More information about the rules-users
mailing list