3

I'm a novice in both Scala and Drools Expert, and need some help getting information out of a Drools session. I've successfully set up some Scala classes that get manipulated by Drools rules. Now I want to create an object to store a set of output facts for processing outside of Drools. Here's what I've got.

I've got a simple object that stores a numeric result (generated in the RHS of a rule), along with a comment string:

class TestResults {
    val results = new MutableList[(Float, String)]()

    def add(cost: Float, comment: String) {
        results += Tuple2(cost, comment)
    }
}

In the DRL file, I have the following:

import my.domain.app.TestResults

global TestResults results

rule "always"
    dialect "mvel"
    when
        //
    then
        System.out.println("75 (fixed)")
        results.add(75, "fixed")
end

When I run the code that includes this, I get the following error:

org.drools.runtime.rule.ConsequenceException: rule: always
    at org.drools.runtime.rule.impl.DefaultConsequenceExceptionHandler.handleException(DefaultConsequenceExceptionHandler.java:39)
...
Caused by: [Error: null pointer or function not found: add]
[Near : {... results.add(75, "fixed"); ....}]
                                                       ^
[Line: 2, Column: 9]
    at org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.getMethod(ReflectiveAccessorOptimizer.java:997)

This looks to me like there's something goofy with my definition of the TestResults object in Scala, such that the Java that Drools compiles down to can't quite see it. Type mismatch, perhaps? I can't figure it out. Any suggestions? Thank you!

Harlan
  • 18,883
  • 8
  • 47
  • 56

3 Answers3

2

You need to initialize your results global variable before executing your session. You can initialize it using:

knowledgeSession.setGlobal("results", new TestResults()))
Go Dan
  • 15,194
  • 6
  • 41
  • 65
  • Yep, that's the step I missed! Error messages were misleading. For completeness, here's the quick-and-dirty code that worked: val results = new TestResults(); ksession.setGlobal("results", results); ksession.fireAllRules(); println(results.results.foldLeft(0.0f)((r,c) => r + c._1)) (Possibly I should put that fold in a method of the results object...) – Harlan Oct 26 '11 at 19:09
  • Were you able to print out the result on the console after the FireAllRules command? I'm doing the same thing except I get no errors and but I am unable to verify what is being returned.... – ProfVersaggi Nov 19 '14 at 04:05
0

Try

import my.domain.app.TestResults

global TestResults results

rule "always"
    dialect "mvel"
    when
        //
    then
        System.out.println("75 (fixed)")
        results().add(75.0f, "fixed")
end

My guess is that the types don't line up and the error message is poor. (75 is an Int, wants a Float)

jsuereth
  • 5,604
  • 40
  • 40
  • Hm, doesn't seem to help. I'm not sure if you meant to have the extra set of ()s in there, but if you do, it doesn't even parse. Without, it still doesn't help: Caused by: [Error: null pointer or function not found: add] [Near : {... results.add(75.0f, "fixed"); ....}] – Harlan Oct 26 '11 at 14:50
-1

That's right.. and try to add a condition to your rule, so it make more sense (the when part). The condition evaluation is the most important feature of rule engines, writing rules without conditions doesn't make too much senses.

Cheers

salaboy
  • 4,123
  • 1
  • 14
  • 15