I must say I am always surprised by the creativity of the users on how to model and solve some use cases. :) Very refreshing to hear!
Let me comment first on the way you are heading and after that how I (Edson) would model the same problem.
What you are doing is, what I would call, a clever way of integrating the rules engine with your application user interface by using the event listeners frameworks. This is kind of the same thing Kris developed for ruleflow groups transition control, if I'm not mistaken, but the difference is that his code being internal, allows him to use some internal APIs to overcome the walls you also hit. Using only the public APIs may not be feasible and using internal APIs may cause undesiring coupling problems for you when drools is upgraded.
My main worry recommending you to continue in the direction you are heading is that you will face additional problems in the future. Just to mention one example, in 5.0 I am implementing support for multi-thread rules evaluation and network partitioning, and as part of this job, I'm removing access to unsafe calls to the agenda that were kind-of available in 4.0 (they were not published as public APIs, but the methods were public).
So, how I would model your solution? Spliting "detection rules" from "action rules" and using logical asserts to make the link between then. I see other possible benefits of that approach, like multiple action options for the same problem or a single action for multiple problems, etc. Let me explain using an example. Pretend you have 2 rules for detecting overheat and overpressure respectivelly:
rule "Detection rule: overheat"
Sensor( temperature > 50 )
insertLogical( new Alarm( Type.OVERHEAT, "some info here") );
rule "Detection rule: overpressure"
Sensor( pressure > 4 )
insertLogical( new Alarm( Type.OVERPRESSURE, "some info here") );
rule "Action rule: open valve"
exists( Alarm( type == Type.OVERHEAT || == Type.OVERPRESSURE ) )
// inform possible solution: open valve
rule "Action rule: increase refrigeration power"
exists( Alarm( type == Type.OVERHEAT ) )
// inform possible solution: increase refrigeration power
So, you see that the actions and detections being used as separate rules allow you to sugest the same solution for multiple problems or just for single problems. Also, you are free to fire your rules all the time, because what informs you about the current status of the system are the Alarm facts that are logically inserted into the working memory.
I don't know if you are familiar with the "logical insert" feature, but if you have an overheat alarm and your temperature goes bellow the threashold (50 in my example), it will detect the change and will automatically retract the alarm fact as it is no longer true that you have an overheat.
You may continue using listeners to update your user interface, by monitoring the Alarm fact assertions instead of the agenda events, or you can also use queries to get the alarms from working memory.
Let us know what you think and if you want to write a use case blog, like we had the other day for a Naval Engineering use case, you are more than welcome!
2008/9/23 Fermion <email@example.com>
I'm doing an expert system for a highly complex high energy physics detector
(CERN->ATLAS->Pixel Detector->Detector Control System).
In principle the detector is a complex machine with a rather hierarchical
The idea is to use a Drools based expert system to inform the operator of
the Detector about what to do in case of a problem. The system itself is
controlled by something that we call a "Finite State Machine" which is
reducing the complex operation of the detector to a number of simple
As the Finite State Machine does not suggest, what to do, if something goes
wrong, the expert system should do that.
In order to do so, the expert system shall display "solution advices" to the
Detector operator. As there can be many unrelated problems at the same time,
we use a tree-structure to show, where in the Detector the problem happened.
If a rule gets activated by a fact (in my case a process parameter of the
detector, e.g. a temperature), the corresponding node in the tree is being
highlighted by a dedicated icon. Once the facts change and the activation is
cancelled, we remove the highlighting icon, so that the tree only shows the
current activations (we don't need logging here, as this is done elsewhere).
This works absolutely fine for us, BUT:
We can't FIRE the activations, as this would immediately remove them from
the agenda, which in turn would remove them from our tree => no operator
would see them.
At first I thought, that NOT-FIRING those activations wouldn't hurt, as we
just wrote the "solution" on the RHS of the rule and parsed this RHS by
ourselves. This way, we displayed the solution belonging to a given
activation as long as it was still on the agenda.
You can see, that the main problem of this is that one CANNOT do things
PrintSolution("Reason for problem is a over-temperature of: " + $temp + "°C
on Module: " + $moduleName);
In our case we could still parse the code, but would be unable to access the
local variables $temp and $moduleName (example) without actually firing the
Firing the rule on the other hand would cancel it's activation, rendering
our display tree useless.
I think the thing that would be most usefull for us would be a way to fire a
rule "silently", without notifying the agenda about it (so that the
activation would NOT be removed).
I'm not sure whether I was able to explain the problem sufficiently, but
maybe someone has an idea how to handle the situation.
Thanks very much!
View this message in context: http://www.nabble.com/firing-rules-without-modifying-activations-tp19623537p19623537.html
Sent from the drools - user mailing list archive at Nabble.com.
rules-users mailing list
JBoss Drools Core Development
JBoss, a division of Red Hat @ www.jboss.com