Details
-
Bug
-
Resolution: Not a Bug
-
Major
-
None
-
7.73.0.Final
-
None
-
2023 Week 03-05 (from Jan 16), 2023 Week 06-08 (from Feb 6)
-
-
Workaround Exists
-
-
NEW
-
NEW
-
75248219
-
---
-
---
Description
OPTIONS
I am not sure what a solution could be, since thee are multiple options, I might be wrong of course.
- Make cache types programmatically accessible so that, through a builder, we could add type mappings to it
- Prevent mappings from being an empty array (maybe this can have a performance impact)
SUMMARY
When I add a rule to a container that has active sessions, and it uses an interface that has never been used in any rule before in the container, that rule is never triggered. But if I reload the whole container that same rule is triggered and works properly.
Drools, possible, bug
It is possible that I made a mistake and therefore that is why it isn't working, and is also why I posted this issue in Stackoverflow prior to come directly to drools ticketing.
Take into account that in this example (you can check on the steps to reproduce everything is detailed with code examples):
adding a rule -> write in KieFileSystem and then incremental build
reloading the container -> buildAll on the given container
When drools agenda needs to decide whether a given rule should be triggered, it uses a class type cache. And my problem is that the cache itself does not contain the same data if I add the rule or if I reload the whole container.
Differences between just adding a rule or reloading the container
Bot examples comes from class ClassObjectTypeConf
getObjectTypeNodes()
public ObjectTypeNode[] getObjectTypeNodes() { if ( this.objectTypeNodes == null ) { this.objectTypeNodes = getMatchingObjectTypes( this.cls ); } return this.objectTypeNodes; }
getMatchingObjectTypes(final Class<?> clazz)
private ObjectTypeNode[] getMatchingObjectTypes(final Class<?> clazz) { final List<ObjectTypeNode> cache = new ArrayList<ObjectTypeNode>(); for ( ObjectTypeNode node : kBase.getRete().getObjectTypeNodes( this.entryPoint ).values() ) { if ( clazz == DroolsQuery.class ) { // for query objects only add direct matches if ( ((ClassObjectType)node.getObjectType()).getClassType() == clazz ) { cache.add( node ); } } else if ( node.isAssignableFrom( new ClassObjectType( clazz ) ) ) { cache.add( node ); } } Collections.sort(cache, OBJECT_TYPE_NODE_COMPARATOR); return cache.toArray( new ObjectTypeNode[cache.size()] ); }
The difference is that when I fire the rules in the fourth step the method getMatchingObjectTypes(final Class<?> clazz) is never invoked since this.objectTypeNodes in getObjectTypeNodes() is an empty array instead of null.
But in the seventh step in the same line of code this.objectTypeNodes is null and therefore getMatchingObjectTypes(final Class<?> clazz) is invoked and the cache is updated for the given entrypoint.
Thanks to this update the agenda will be able to "know who SomeInterface is" and therefore trigger the rule.
Of course if we are in the fourth step and, instead of allowing the flow to go normally, we change this.objectTypeNodes to null (basically forcing drools to restart the cache for this entrypoint) everything will work smoothly.