I am using RedHat drools DMN capability. I have set up a 'DMNRuntimeEventListener' in order to collect information about the decision table that has just run. In that event listener there is a callback method afterEvaluateDecisionTable
which is called. That method receives a AfterEvaluateDecisionTableEvent
object. That object does not provide a pointer to the DecisionTable
that it just executed.
Instead, that object provides (1) the name of the decision node, and (2) the name of the decision table. This is a little odd because the DecisionTable
object does not have a name. It has an id, and a label. But it does not have a getName()
method or anything that I can find related to that.
I have the DMNModel
object for the model that is being executed. From that, it is easy to find the DecisionNode
by name, and the name given works. If the entire decision node is a decision table, then I don't need the decision table name, and everything works fine.
But DMN allows you to nest decision tables with other expression structures, such as a Context object. Context objects can be nested within other Context objects. So the decision node can be an elaborate tree with multiple DecisionTable
objects within it. In this case, I need to find the decision table by name.
I can iterate through the tree of children, and occasionally I find objects that are in fact instanceof DecisionTable
objects. OK, all I need to do is to find the name of that decision table.
getId()
returns a GUID and does not match the name givengetLabel()
returns a nullgetIdentifierString()
returns the same as getId()
I was pointed to this example code for getting a name:
public static String nameOrIDOfTable(DecisionTable sourceDT) {
if (sourceDT.getOutputLabel() != null && !sourceDT.getOutputLabel().isEmpty()) {
return sourceDT.getOutputLabel();
} else if (sourceDT.getParent() instanceof NamedElement) { // DT is decision logic of Decision, and similar cases.
return ((NamedElement) sourceDT.getParent()).getName();
} else if (sourceDT.getParent() instanceof FunctionDefinition && sourceDT.getParent().getParent() instanceof NamedElement) { // DT is decision logic of BKM.
return ((NamedElement) sourceDT.getParent().getParent()).getName();
} else {
return new StringBuilder("[ID: ").append(sourceDT.getId()).append("]").toString();
}
}
This suggests looking at the following and here at the values that I get:
getOutputLabel()
is nullNamedElement
and does not have a getName()
methodNamedElement
and does not have a getName() methodSo this method would generate a name for the decision table, but it does not match the name I have been given by the listener. No method provides the name of the decision table (feature request: it would be really nice if the listener callback just provided a link to the DecisionTable
object)
So then I start looking into the drools source to figure out how the evaluation code finds the name. What I find is that the name is PASSED IN to the evaluation method, so the name of the decision table depends on the method that calls for evaluation. I would have to analyze all the code that calls for evaluation, in order to determine what this value for decisionTableName means, because it seems to mean different things depending on who is calling for the evaluation.
Can anyone suggest a CORRECT way to find the name of the decision table that will always correspond to the name that the listener callback has provided?
The most appropriate way for your real use-case (correlate AfterEvaluateDecisionTableEvent
with the "xml" DecisionTable
element) would be to go via element ID.
To locate a DecisionTable
in a given DMNModel
, you can use something similar to this one-liner:
public static DecisionTable locateDTbyId(DMNModel dmnModel, String id) {
return dmnModel.getDefinitions()
.findAllChildren(DecisionTable.class)
.stream().filter(d -> d.getId().equals(id))
.findFirst().orElseThrow(IllegalStateException::new);
}
as for the listener events for the Decision Table before/after to be augmented with the decision table ID, PR is submitted, ref https://github.com/kiegroup/drools/pull/4860
This would align, for instance, to ContextEntry event logic as well (there again ID are used).
Thanks for having reported the gap, for feature request you can follow the instruction in https://www.drools.org/community/getHelp.html