How to use Hashtable in Rules Engine. And objects within objects in rules
I have an object containing Hashtable. I want to take the value from the hashtable and use it for the LHS side of the rule. How do I do that?
Object: Test
Hashtable in Test: inputHT (the hashtable contains the key as 'age' and value as '21'. Like: inputHT.put(age, new Integer(21)) )
The rule defined is:
rule "male"
when
t:Test(inputHT.get("age") >= 21)
then
System.out.println("Adult");
end
It throws error as: unexpected token 'inputHT'
mismatched token .... expecting type )......
Please reply soon
Also tell me how to use variables in Object within another object in Rules defining process.
For eg: A variable skill1 (String) present in Skill object, which in turn is present in Employee object. How to define the rule for skill1.
[849 byte] By [
Vivona] at [2007-10-3 6:33:38]

First of all the mismatch in the example could have 2 sources from the code that you showed
when you say that the value age got into the hash table by way of
inputHT.put(age, new Integer(21))
perhaps you meant
inputHT.put("age", new Integer(21))
if I assume that you got the value into your hash table correctly, the other potential problem is that you didn't cast it correctly on removal i.e. when you do inputHT.get("age") what do you think is the return type?
Probably Object which you the try to use as an argument for a numeric comparison like >=
Perhaps you want to cast the results of your hashtable fetch to Integer before you compare and once you are actually comparing two Integers (not ints) you might want to use an Integer method for that.
As to you second question, I can't guess what you are trying to do. How do you use variables in Object... ? Well, normally you use them however you want to use them, within the limits of the Java language of course.
Perhaps if you described what you are doing we could help.
Thank u for the reply. But I will explain you what i am trying to do.
This is something to do with the JBoss Rules Engine.
I have an object called 'Employee' containing variables name(string), age(int), sex(string), an object Skill and other fields not relevant.
Now the Skill object contains name and desc as variables.
And now i have another seperate object called Test containing two hashtable: inputHT and outputHT.
i have appropriate data in each of the objects and the hashtable:
Employee e = new Employee();
e.setName("Name");
e.setAge(18);
e.setSex("f");
e.getSkill().setSkill("Trainer");
Hashtable ht = new Hashtable();
ht.put("age", new Integer(e.getAge());
ht.put("sex", e.getSex());
Test t = new Test();
t.setInputHT(ht);
Since this is something to do with drools rules: I have the appropriate code even for that.
Like obtaining the rules defined(.drl files) in a stream, constructing the package builder, rulebase and the working memory.
I will now explain u my .drl files(ie the rules that i have defined) and the error that i am encountering
when I have the rule as the following there is no error:
rule "testRule1"
when
e:Employee(age >= 18, sex == "f")
then
System.out.println("The lady can marry");
end
In the above rule we can see that only two simple variables contained in the employee object is being accessed and there is no error encountered.
But when I try to access the object "skill" in the employee object, the rule throws me an error when i am constructing the packageBuilder:
rule "testRule2"
when
e:Employee(skill.name == "Trainer")
then
System.out.println("The skill is trainer");
end
The error thrown is : unexpected token 'skill' and many other dump errors and also error: expected token ')'
I tried changing the when clause as the following:
when
e:Employee(skill.getName() == "Trainer")
and also
when
e:Employee(skill.getName().equals("Trainer"))
All of them throws the same above error.
But at the same time if i access only object without its variables, it is working fine. Like:
rule "testRule2"
when
e:Employee(skill == "Trainer")
then
System.out.println("The skill is trainer");
end
The above rule works properly and does not throw any error. But it is not a valid rule. But syntactically it is correct. and does not throw any error during packageBuilder.
Similarly, the problem is with the Hashtable
The below code works fine, but rulewise it is not valid, but syntactically correct. and does not throw any error
rule "testHT1"
when
t:Test(inputHT == "f")
then
System.out.println("Print this");
end
But the following code throws error, telling unexpected token 'inputHT' :
rule "testHT1"
when
t:Test(inputHT.get("sex") == "f")
then
System.out.println("Lady");
end
I even changed the when clause, but did not get the appropriate result and it threw me error.
when
t:Test(((String)input.get("sex")) == "f")
and also many other variants but of no use.
It would be of great help if u or anyone else could reply to this with some solution
Tahnk you in advance
I do not have a solution for you since I know nothing about the JBoss Rules Engine, however from looking at the code samples that you supplied I have a guess as to why it does not work.
Your rules are not java code
whenxxxxxthen yyyy end
the words "when", "then", "end" are not java keywords. The stuff that you put in for xxx and yyy look like java expressions but my guess is that they are NOT actually java expressions.
You have some rule system that someone wrote that reads these rules and generates some code from them. You supply the rules, the system reads them and turns them into code which will grovel around over your data in some way.
While it would have been nice if the rule reading system could take in any legal java statement, all the evidence of your examples shows otherwise.
Anytime you use a method - like .name or .getName() the rule system barfs
It appears that it was only built to handle simple arithmetic like == or > done on simple predefined classes like strings and ints but not on your internally defined members like an object of type Skill.
so
name = "foo" works but
skill.name = "foo" fails
(because you had to chain down inside a complex type Skill)
Your comment about the line
inputHT = "f"
is similar.
This is not type correct as a java statement. The java compiler which checks types will complain about a statement like that but the rule system is NOT a java compiler or even a subset of a java compiler. It is just its own language with its own grammar and it only partly resembles java.
So what to do? A couple of possibilities suggest themselves.
1) abandon the JBoss Rules Engine and write your own rules code
2) read the documentation on what is actually allowed in JBoss Rules and redesign your system to fit within those constraints.
Of course now that you have mentioned JBoss Rules by name there is the possibility that someone has worked with them and can give some more direct advice.
Thank you for your valuable information and tips. Though i did not get the solution, the info provided would be of some help to others. Probably I need to get a better understanding of the jboss rules.
I have seen this error on some similar code (though it was not jboss) and was able to fix it by using the .equals route instead of == operator to compare strings. Not sure if this will work for your situation, but it's worth a shot.
JPNa at 2007-7-15 1:21:17 >

Did you ever get an answer and solution?I have the exact same problem.
Oh,You have exact same problem!
Well, in that case the exact same advice should work. Let me reframe it slightly as a rule based system.
IF (learning to use JBoss rule system is a pain AND it doesn't do the thing you want) THEN blow it off and write your own code in Java.
Is writing rule based systems difficult in Java? Not really. Notice how easily I can write rules in java.
if (someRattyJavaExpressionAppliedTo(someBogusJavaObjectStructure)){
doSomethingTo(someBogusJavaObjectStructure);
}
Notice how these rules can be any legal java expression what so ever. Also you can simply place one rule right after the other one. You can place them in any order, and the only ones that fire will be the ones that have the correct preconditions.
The ONLY penalty that you pay for doing your rules this way in direct java code is that you run the test expression for every single rule in order to find the one rule that applies. This means that your runtime is N*L (where N is the number of rules and L is the length of your derivation) instead of being L (which is what you COULD get if your rules happen to all have some MAGIC simple hashing based way to tell when a rule matches a precondition - note, not all systems permit magic. That is what you are fighting against. presumably jBoss can accelerate some of the rule matching by forcing you to construct rules of a certain type. If you want to have more complicated rule types then JBoss is not the tool for you)
Recall the sage advice: "Premature optimization is the root of all evil computer code."
IF have already built your expert system in vanilla java, AND you have found that it runs too slowly, AND the slowdown is caused by having too many rule to test tests, AND you are thus FORCED into doing some optimization in the rule look up, THEN you have some work ahead of you, but OTHERWISE just do the easy thing, write your rules in nice simple Java and don't optimize.
I would venture to guess that 95% of the expert systems that ever get built, never populate the system with enough rules so that accelerating the look up makes the slightest difference in runtime. Focus your energy into developing your rules, not in understanding someone's clumsy free rule evaluation system. Once you know the set of rules that you need then you can look at optimizing.
