[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