The Coder
The Coder

Reputation: 2632

Passing multiple objects in Drools not working

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

Answers (2)

laune
laune

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

user489041
user489041

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

Related Questions