1

I am working on a drool(drl) POC in which I create java beans at run time using reflection. I have set the below property in the config:

KnowledgeBuilderConfiguration config = KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration();
config.setProperty("drools.dialect.default", "mvel");

//drl sample:
package script.demo
dialect "mvel"
import Employee;
rule "Rule - 1"
    when
        $emp: Employee($emp_id: emp_id)
    then
        System.out.println("emp id: "+$emp.emp_id);
end

But I am getting below error:

Field Reader does not exist for declaration '$emp_id' in '$emp_id: emp_id' in the rule 'Rule - 1' : [Rule name='Rule - 1'] @line [I@4cb9v654...............

Request help, how to solve this?

Pawan Singh
  • 63
  • 2
  • 12
  • Sounds like there's something wrong with how your project is set up. It also sounds like you're using some very very very old version. But you've provided none of this information -- how your project is set up, how you load rules, how you fire rules, what version of drools you are using -- so it's not really possible to help you. – Roddy of the Frozen Peas Jul 14 '20 at 15:39
  • That being said it does sound like this 'Employee' class in the default package does not have a public `getEmp_id()` method (or a public `emp_id` variable.) But since you've not given us any information to work with that's really just a guess. – Roddy of the Frozen Peas Jul 14 '20 at 15:40
  • Thanks for the reply, PFB the answers: 1. Project Setup: pure maven project with drools dependency like, kie-api, drools-core, drools-compiler 2. Loading rules: KnowledgeBuilderConfiguration config = KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration(); config.setProperty("drools.dialect.default", "mvel"); KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(config); FileInputStream fis = new FileInputStream("script/demo/test.drl"); ... KieSession kieSession1 = kieBase1.newKieSession();kieSession1.fireAllRules(); 3. drool version - 7.39.0.Final – Pawan Singh Jul 14 '20 at 16:07
  • For the 2nd point, You are right I don,t have a static bean class.. I create at runtime using reflection .. and because of this I am using mvel.. PFB code snippet for Employee bean: public static Class buildBean(String className, StructType df_schema) {Object pojoBean = Reflect.compile( "com.demo." + className,"package com.demo.drools;\n" +"@Data\n" +"@NoArgsConstructor\n" + "@AllArgsConstructor(access = AccessLevel.PUBLIC)\n" + "public class " + className + " implements Serializable {\n" + getFieldsString(df_schema) +"}").create().get();return pojoClass.getClass(); – Pawan Singh Jul 14 '20 at 16:15
  • How do you expect the rules to be compiled when the class you reference in them doesn't exist yet? – Roddy of the Frozen Peas Jul 14 '20 at 23:55
  • Actually using Lombok to generate the boiler-plate code.. I have Lombok integrated with Drools – Pawan Singh Jul 15 '20 at 10:16
  • You just stated that there is no Employee.java file and you're generating the class using reflection. Lombok isn't relevant to that. Drools can't make use of Employee if Employee doesn't exist at the time the rules are compiled. – Roddy of the Frozen Peas Jul 15 '20 at 19:20
  • FWIW I came across a similar issue where the following caused a 'Field Reader does not exist for declaration '$recName' in '$recName : name' error: $rec : MyClass ( $recName : name ) even though MyClass does have a public name property. Strangely enough it works when I change it to: $rec : MyClass ( $recName : this.name ) – Jelle van Geuns Dec 16 '20 at 07:26

1 Answers1

1

The error is trying to say that your Employee class has no field or method that it can access to map to the $emp_id variable you've declared.

It looks for either a public method prefixed with 'get', or a public variable named as-is.

An Employee class definition that looks like either of the following will resolve the error.

Option 1: declare a public variable emp_id.

public class Employee {
  public String emp_id;
}

Option 2: declare a public method called getEmp_id.

public class Employee {
  public String getEmp_id() { return "..."; }
}

Either of these options will resolve the issue and allow you to bind the $emp_id variable in your rule:

Employee( $emp_id: emp_id )

(I would recommend, of course, renaming to empId and then implementing either such a variable or a getEmpId method, since that follows Java naming conventions. You can still call your declared variable in the drools $emp_id of course.)

Roddy of the Frozen Peas
  • 14,380
  • 9
  • 49
  • 99