Drools 7 中function调用global报错问题

在技术群里遇到网友问到一个function 调用global报错的问题,这里写个程序复现一下先。

1.定义一个service 一会儿作为global set到drools kiesession


package com.helloworld.Service;

public class TestService {
    public void testGlobal(String str){
        System.out.println("java application print:"+str);
    }
}

2. DRL文件

package com.hello;
global com.helloworld.Service.TestService myService

function boolean myfunction(String str){
    myService.testGlobal(str);
    return true;
}

rule "testGlobal"
    when
        eval( myfunction("hello global",myService))
    then
    System.out.println("rule print success!");
end

3.调用

KieServices ks = KieServices.Factory.get();
KieContainer kc = ks.getKieClasspathContainer();
KieSession session = kc.newKieSession();

//创建TestService实例对象,加入到drools
TestService service = new TestService();
session.setGlobal("myService",service);
//触发规则
session.fireAllRules();

4.报错

Exception in thread "main" java.lang.RuntimeException: Error while creating KieBase[Message [id=1, kieBase=defaultKieBase, level=ERROR, path=E:\ideaTest\droolsTemplate\target\classes\testGlobal.drl, line=5, column=0
   text=[ function myfunctionmyfunction (line:5): myService cannot be resolved
 ]], Message [id=2, kieBase=defaultKieBase, level=ERROR, path=E:\ideaTest\droolsTemplate\target\classes\testGlobal.drl, line=10, column=0
   text=Rule Compilation error The import com.hello.Myfunction cannot be resolved
The method myfunction(String, TestService) is undefined for the type Rule_testGlobal1826430642], Message [id=3, kieBase=defaultKieBase, level=ERROR, path=E:\ideaTest\droolsTemplate\target\classes\testGlobal.drl, line=-1, column=0
   text=Error importing : 'com.hello.Myfunction.myfunction']]
	at org.drools.compiler.kie.builder.impl.KieContainerImpl.getKieBase(KieContainerImpl.java:377)
	at org.drools.compiler.kie.builder.impl.KieContainerImpl.getKieBaseFromKieSessionModel(KieContainerImpl.java:575)
	at org.drools.compiler.kie.builder.impl.KieContainerImpl.newKieSession(KieContainerImpl.java:551)
	at org.drools.compiler.kie.builder.impl.KieContainerImpl.newKieSession(KieContainerImpl.java:458)
	at org.drools.compiler.kie.builder.impl.KieContainerImpl.newKieSession(KieContainerImpl.java:441)
	at com.helloworld.action.TestGlobalAction.main(TestGlobalAction.java:12)
14:44:54.995 [main] ERROR org.drools.compiler.kie.builder.impl.KieProject - Unable to build KieBaseModel:defaultKieBase
[ function myfunctionmyfunction (line:5): myService cannot be resolved
 ]
Rule Compilation error : [Rule name='testGlobal']
	com/hello/Rule_testGlobal1826430642.java (2:138) : The import com.hello.Myfunction cannot be resolved
	com/hello/Rule_testGlobal1826430642.java (8:445) : The method myfunction(String, TestService) is undefined for the type Rule_testGlobal1826430642

Error importing : 'com.hello.Myfunction.myfunction'

5.猜想

从异常信息中可以看出是创建默认KieBase 时出现的异常,创建知识库报错基本可以认为是DRL编写有问题。

function是放在drl源文件中的代码块,其本质就是个函数,用来抽取和封装具有参数不同,但处理具有相同代码逻辑。再来看Global 它实际是某数据类型的实例对象,尽管Global是全局的,但是函数里直接调用实例……Emm……,那猜测大概就是这里有问题吧。基于这个猜想我给出一个改造方案。

6.改造DRL文件,将Global 变量作为参数传递到function,function通过形参调用Global,如下:

package com.hello;
//引入Global中实例对象的数据类型
import com.helloworld.Service.TestService
//引入Global
global com.helloworld.Service.TestService myService
//function 增加 Global 中实例对象的数据类型 的形参
function boolean myfunction(String str,TestService t){
    //通过形参调用Global中实例对象的方法
    t.testGlobal(str);
    return true;
}

rule "testGlobal"
    when
        //将Global 中实例对象作为参数传入function
        eval( myfunction("hello global",myService))
    then
    System.out.println("rule print success!");
end

执行结果:

java application print:hello global
rule print success!

嗯!OJBK!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是一个在Drools实现复杂function的例子: ``` package com.example.drools; import java.util.List; import org.drools.core.spi.KnowledgeHelper; public class DroolsFunctions { public static boolean isMultipleOfThree(int number) { return number % 3 == 0; } public static void printNumbers(List<Integer> numbers, KnowledgeHelper helper) { for (Integer number : numbers) { if (isMultipleOfThree(number)) { helper.printOut(number + " is a multiple of three."); } else { helper.printOut(number + " is not a multiple of three."); } } } } ``` 在这个例子,我们定义了两个function: 1. `isMultipleOfThree`:判断一个整数是否是3的倍数。 2. `printNumbers`:接收一个整数列表和Drools的`KnowledgeHelper`,对于列表的每个数,如果它是3的倍数,则打印出它是3的倍数,否则打印出它不是3的倍数。 注意,为了在Drools使用这些function,我们需要将它们定义在一个Java类,并将这个类作为Drools规则文件的一个全局变量导入。例如: ``` package com.example.drools; import java.util.Arrays; import org.drools.core.spi.KnowledgeHelper; global com.example.drools.DroolsFunctions droolsFunctions; rule "Print Numbers" when $numbers: List(size > 0) then droolsFunctions.printNumbers($numbers, drools.getKnowledgeHelper()); end rule "Is Multiple of Three" when Number($value: intValue) eval(droolsFunctions.isMultipleOfThree($value)) then System.out.println($value + " is a multiple of three."); end ``` 在这个规则文件,我们将`DroolsFunctions`类作为一个全局变量`droolsFunctions`导入,并在两个规则使用它。在第一个规则,我们调用`printNumbers`函数来打印出列表的每个数是否是3的倍数。在第二个规则,我们使用`eval`语句来判断一个数是否是3的倍数,并打印出相应的信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值