try { Rete engine = new Rete(); engine.executeCommand("(gibberish!)"); } catch (JessException re) { /* ignore errors */ }If you ignore the Java exceptions, you will miss Jess's explanations of what's wrong with your code. Don't laugh - more people code this way than you'd think!
Anyway, as an example, if you attempt to load the folowing rule in the standard Jess command-line executable,
Jess> (defrule foo-1 (foo bar) -> (printout "Found Foo Bar" crlf))You'll get the following printout:
Jess reported an error in routine Jesp.parseDefrule. Message: Expected '=>' . Program text: ( defrule foo-1 ( foo bar ) -> at line 2. at jess.Jesp.parseError(Jesp.java:1434) at jess.Jesp.doParseDefrule(Compiled Code) at jess.Jesp.parseDefrule(Jesp.java:882) at jess.Jesp.parseSexp(Jesp.java:153) at jess.Jesp.parse(Compiled Code) at jess.Main.execute(Compiled Code) at jess.Main.main(Main.java:26)This exception, like all exceptions reporte by Jess, lists a Java routine name. The name parseDefrule makes it fairly clear that a rule was being parsed, and the detail message explains that -> was found in the input instead of the expected => symbol (we accidentally typed -> instead). This particular error message, then, was fairly easy to understand.
Runtime errors can be more puzzling, but the printout will generally give you a lot of information. Here's a rule where we erroneously try to add the number 3.0 to the word four:
Jess> (defrule foo-2 => (printout t (+ 3.0 four) crlf))This rule will compile fine, since the parser doesn't know that the + function won't accept the atom four as an argument. When we (reset) and (run), however, we'll see:
Jess reported an error in routine Value.numericValue while executing (+ 3.0 four) while executing (printout t (+ 3.0 four) crlf) while executing defrule foo-2 while executing (run). Message: Not a number: "four" (type = ATOM). Program text: ( run ) at line 4. at jess.Value.typeError(Value.java:361) at jess.Value.typeError(Value.java:356) at jess.Value.numericValue(Value.java:244) at jess.Plus.call(Compiled Code) at jess.FunctionHolder.call(FunctionHolder.java:35) at jess.Funcall.execute(Funcall.java:238) at jess.FuncallValue.resolveValue(FuncallValue.java:33) at jess.Printout.call(Compiled Code) at jess.FunctionHolder.call(FunctionHolder.java:35) at jess.Funcall.execute(Funcall.java:238) at jess.Defrule.fire(Compiled Code) at jess.Activation.fire(Activation.java:58) at jess.Rete.run(Compiled Code) at jess.Rete.run(Compiled Code) at jess.HaltEtc.call(Funcall.java:1559) at jess.FunctionHolder.call(FunctionHolder.java:35) at jess.Funcall.execute(Funcall.java:238) at jess.Jesp.parseAndExecuteFuncall(Jesp.java:1423) at jess.Jesp.parseSexp(Jesp.java:172) at jess.Jesp.parse(Compiled Code) at jess.Main.execute(Compiled Code) at jess.Main.main(Main.java:26)In this case, the error message is also pretty clear. It shows the offending function (+ 3.0 four) then the function that called that (printout) then the context in which the function was called (defrule foo-2), and finally the function which caused the rule to fire (run).
Looking at the stack trace, starting from the top down, you can find entries for the + fucntion (Plus.call()), the printout function, the rule firing (Defrule.fire()) and the run command (Rete.run()).
The message 'Not a number: "four" (type = ATOM).' tells you that the + function wanted a numeric argument, but found the symbol (or ATOM) four instead.
If we make a similar mistake on the LHS of a rule:
Jess> (defrule foo-3 (test (eq 3 (+ 2 one))) => )We see the following after a reset:
Jess reported an error in routine Value.numericValue while executing (+ 2 one) while executing (eq 3 (+ 2 one)) while executing 'test' CE while executing rule LHS (TECT) while executing (reset). Message: Not a number: "one" (type = ATOM). Program text: ( reset ) at line 4. at jess.Value.typeError(Value.java:361) at jess.Value.typeError(Value.java:356) at jess.Value.numericValue(Value.java:244) at jess.Plus.call(Compiled Code) at jess.FunctionHolder.call(FunctionHolder.java:35) at jess.Funcall.execute(Funcall.java:238) at jess.FuncallValue.resolveValue(FuncallValue.java:33) at jess.Eq.call(Compiled Code) at jess.FunctionHolder.call(FunctionHolder.java:35) at jess.Funcall.execute(Funcall.java:238) at jess.FuncallValue.resolveValue(FuncallValue.java:33) at jess.Test1.doTest(Test1.java:95) at jess.NodeTest.runTests(Compiled Code) at jess.NodeTest.callNode(Compiled Code) at jess.Node.passAlong(Compiled Code) at jess.Node1TECT.callNode(Compiled Code) at jess.Rete.processTokenOneNode(Rete.java:1009) at jess.Rete.processToken(Compiled Code) at jess.Rete.assert(Rete.java:754) at jess.Rete.reset(Rete.java:680) at jess.HaltEtc.call(Funcall.java:1565) at jess.FunctionHolder.call(FunctionHolder.java:35) at jess.Funcall.execute(Funcall.java:238) at jess.Jesp.parseAndExecuteFuncall(Jesp.java:1423) at jess.Jesp.parseSexp(Jesp.java:172) at jess.Jesp.parse(Compiled Code) at jess.Main.execute(Compiled Code) at jess.Main.main(Main.java:26)Again, the error message is very detailed, and makes it clear, I hope, that the error occurred during rule LHS execution, in a test CE, in the function (+ 2 one). Note that Jess cannot tell you which rule this LHS belongs to, since rule LHSs can be shared.
Jess uses the equals and hashCode methods of any objects added to a slot in a Jess fact. As such, it is very important that these methods be implemented properly. The Java API documentation lists some important properties of equals and hashCode, but I will reiterate the most important (and most often overlooked) one here: if you write equals, you probably must write hashCode too. For any two instance of a class for which equals returns true, hashCode must return the same value. If this rule is not observed, Jess will appear to malfunction when processing facts containing these improperly defined objects in their slots. In particular, rules that should fire may not do so.