Wednesday, July 14, 2004

Dinner
I didn't log my work last night as I was in a hurry to get out to a restaurant with Anne. It was Bastille Day, and a lovely little French restaurant has just opened just a few doors away.

However, it seems that some of the guys here at work have been hanging on my every word, and I've been chastised for my laxity. So I thought I'd better put in a quick update. Besides, it helps with my intention of logging what I'm doing, so I can come back and have a look at it if need be.

Rules
Yesterday was spent debugging the rules. First of all, I needed to properly load the rules, and I found that I couldn't load up the .drl XML file that holds all the rules and code. I assumed that this meant it needed to be in the jar file as a kind of resource, so I built a script which did all the compiling and jarring for me (some of this was done on Tuesday, and I finished it on Wednesday). It's not big enough to justify setting up Ant at this point.

Unfortunately I was now getting an error telling me that there was no method named buildFromUrl on RuleBaseBuilder. This was a bit confusing, since the example code all used this, so I went grepping. I discovered that Drools has a RuleBaseBuilder class in org.drools and another in org.drools.io. While I can see the convenience of being able to use the same class name in different packages, I've never approved of it when it can be avoided. It forces anyone using these classes to be explicit about packages whenever they use the class. Still, it was easily to fix once I found the problem, and I could start loading the .drl file.

Since Drools does a lot of interpreting of Java code inside of the XML, I was often getting errors telling me that parsing or execution was unsuccessful, but with no information as to what the problem was. One block of code in particular was quite long, and a failure in there was causing me all sort of grief.

Once I had this going, I found that all my &rdf; and &rdfs; entities were not being parsed by iTQL in the way I exepcted. After speaking with AN I discovered that the GUI automatically loads a file to create aliases for these entities. I had assumed that these aliases were built in, but it makes sense that they're not. For some reason I had also assumed that user aliasing would be done by the GUI (since one helpful effect of aliasing is to reduce typing), but the connection does it instead. So I went through the GUI code, and discovered that it is loading a file named default-pre.itql, which in turn holds the namespace aliases that I needed. I now have the Bootstrap code inserting these aliases for me. Better that than making the queries less readable with lots of redundant namespace info.

As an aside, while setting the Bootstrap class up I discovered that ItqlInterpreterBean does not accept uppercase commands. Way back when I was programming databases I used to put all SQL keywords in uppercase as a matter of course, so this one tripped me up. The error I was receiving was unhelpful too, telling me that it expected an EOF in the statement.

Finally I found that the rules were not executing as I expected. It kept executing the same rules over and over again. Lots of logging later I found the reason. Drools takes advantage of cached results of its preconditions in order to determine if a rule needs to be run. I know that Drools does this to avoid running rules. However, I had subconsciously assumed that this optimisation was only used to avoid running tests, but that it would always run the tests if it thought that the rule does need to be executed. Only it doesn't run the tests at all.

The logs finally showed me that all the tests for the rule were being run, with the exception of the test that indicated that the data had not changed and hence no insertion would be necessary. This was because the object in question had not had drools.modifyObject called on it, so the Drools framework saw no need to test any conditions which used that object. Since Drools did call the tests in the other condition statements, the system is obviously parsing the statements to find the objects being tested in them. This is a little more complicated than simply interpreting and running code found in a statement.

Once everything was going I run headlong into a ClassCastException coming out of an insert statement. I've now found out why, but not before leaving yesterday, so I'll leave that description until the next day's entry.

No comments: