Search code examples
drools

how to use global variable in drools


I have a drools file (.drl) which I am using to trigger rules. I have declared a global variable in the same file. However I am unable to use the same.

DRL:

global Boolean testValue                              // line 1
System.out.println("Global testValue: "+testValue)    // line 2

When I call the rules, I get an error on line 2. The testValue is being populated prior to calling.

Any suggestion, or where I am going wrong? I am certain this is not a syntax error.


Solution

  • You actually do have a syntax error. It's on line 2, like your error had indicated, not line 1.

    global Boolean testValue                              // line 1
    System.out.println("Global testValue: "+testValue)    // line 2
    

    Just like you can't have a System.out.println floating anywhere inside of a Java class (it has to be inside of a method), you can't have one floating anywhere inside of a DRL file (it has to be inside of a rule.)

    The easiest way to do what you're trying to do here is to create an 'empty' rule and run your println in the then clause.

    global Boolean testValue
    
    rule "Print global value"
    when
      // leave this empty so it always fires
    then
      System.out.println("global value: " + testValue);
    end
    

    You are correct that there is no syntax problem with your global declaration.


    For completeness, and to answer the question in your question's title (though not the body), the way you use a global value is like this.

    • Globals must be objects (you can't use a primitive)
    • Globals can be modified but changes can't be read

    First, in your DRL, you declare the global using the syntax global <type> <name>. It does not get assigned a value in the DRL.

    Second, where you're firing your rules, you set the global value. Since this is an object, you maintain the object reference outside of the rules, and any changes to that object in the rules will be reflected once the rules finish executing.

    var value = ...; // some OBJECT which you are going to pass in as a global
    
    KieSession session = ruleBase.newStatefulSession();
    session.insert(...); // insert data
    session.setGlobal( "myGlobalFoo", value ); // sets the global; note the name must match the rule file!
    session.fireAllRules();
    

    It's very important that the name that you used in the DRL is the same name that you use in setGlobal.

    Then you can use your global.

    • In the "when" clause you can read the original value of the global. This is useful if you want to pass in constants of some kind -- I've worked with rules that pass in local tax rates, commission rates, various physics constants, user permissions, etc.
    • In the "then" clause you can update the value of the global, with the expectation that the values will be retained once the rules finish executing. These updated values cannot be relied on to be visible in other rules. Back in the old days (Drools 5 and earlier), it was not uncommon to have a global 'rule output' object of some type that the rules would update as they executed.