Reputation: 2632
I've created a statefull knowledge session which I'm using to insert multiple objects in the session.
StatefulKnowledgeSession ksession = initializeDrools(runtimeDrlFile.getFilePath());
private StatefulKnowledgeSession initializeDrools(String filePath) throws Exception {
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newFileResource("E:\\drools\\" + filePath), ResourceType.DRL);
KnowledgeBase kbase = kbuilder.newKnowledgeBase();
kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
return kbase.newStatefulKnowledgeSession();
}
Assume I've two maps, like
Map<String, Object> map = new HashMap<String, Object>(); // Assume somthing is stored in it
Map<String, Object> maps = new HashMap<String, Object>(); // ""
Now I've inserted both objects into ksession and fired all rules.
ksession.insert(maps);
ksession.insert(map);
ksession.fireAllRules();
This is my drools file.
import java.util.Map;
rule "Category Level"
when
$map: Map( this["CategoryCode"] == "10" && this["CategoryAmount"] >= 1000 )
then
$map.put("Discount", String.valueOf("10.00"));
System.out.println($map);
System.out.println($maps);
end
It's showing me as
Caused by: java.lang.IllegalArgumentException: Could not parse knowledge.
If I remove System.out.println($maps);
, it's working correctly. If I replace all occurences of $map
with $maps
in drl file, its working fine too but now I'm not able to access $map
and vice versa.
Is there anything wrong with my logic of passing multiple objects into drools?
Update:
After clearing the Illegal Arguments Exception,
import java.util.Map;
rule "Category Level"
when
$maps: Map()
$map: Map( this["CategoryCode"] == "10" && this["CategoryAmount"] >= 1000 )
then
$map.put("Discount", String.valueOf("10.00"));
System.out.println($map);
System.out.println($maps);
end
Now the problem is both the sysout
is printing the value of $map
. Why $maps
value is replaced with $map
?
Upvotes: 1
Views: 4885
Reputation: 31290
A pattern like
$mx: Map()
is capable of binding any Map inserted as a fact. So, if you have a couple of patterns
$mx: Map()
$my: Map()
a single map will bind as $mx and $my. If you have two maps, a and b, they'll be bound in a fourfold way: a-a, a-b, b-a, b-b.
Adding a constraint to a pattern, e.g.,
$mx: Map( this["CategoryCode"] == "10" && this["CategoryAmount"] >= 1000 )
restricts the possible matches and bindings, but adding another pattern:
$mx: Map( this["CategoryCode"] == "10" && this["CategoryAmount"] >= 1000 )
$my: Map()
will still produce multiple matches, e.g., with two maps as facts and one of these maps matching the first pattern, you'll still get a-a, a-b.
java.util.Map and other "anonymous" container classes (maps and all Collections) are notoriously tricky for matching. If a map represents some "real world" entity, it should have an entry providing unique identification. Use this in all patterns.
Preferably, Java beans should be used as facts, with some field providing identification.
Upvotes: 2
Reputation: 28304
You dont define $maps
anywhere. You need to declare it and assign it a value.
You want something like this:
$map: Map( this["CategoryCode"] == "10" && this["CategoryAmount"] >= 1000 )
$maps: Map()
Upvotes: 1