2012-07-03 33 views
2

我正在使用drools来评估某些对象的系统上工作。但是,这些对象可以是使用jodd在运行时加载的类。我可以使用以下函数加载文件:用jodd加载类并在流口水中使用它们

public static void loadClassFile(File file) { 
    try { 
     // use Jodd ClassLoaderUtil to load class into the current ClassLoader 
     ClassLoaderUtil.defineClass(getBytesFromFile(file)); 
    } catch (IOException e) { 
     exceptionLog(LOG_ERROR, getInstance(), e); 
    } 
} 

现在让我们说我创建了一个名为Tyre的类,并使用上面的函数加载它。有没有一种方法,我可以使用轮胎类在我的规则文件:

rule "Tire Operational" 
when 
    $t: Tire(pressure == 30) 
then 

end 

现在,如果我尝试添加此规则,我得到一个错误说无法解析对象类型轮胎。我的假设是,我会以某种方式需要导入轮胎的规则,但我不知道如何做到这一点。

+0

我试着在规则文件中写入“import datatypes.Tire”。 (数据类型是轮胎类应该包含的包)。现在不是说不能解决轮胎问题,而是说不能解决轮胎问题。所以我解释这是因为Tyre正在被解析为一个包而不是一个类型,因此不能被导入。为什么会这样呢? –

回答

1

从版本3开始就没有使用Drools,但会尝试帮助。当你以这种方式加载类时(动态的,在运行时,不管你是否使用例如Class.forName()或Jodd),加载的类名都不能在代码中显式使用。我相信我们可以用下面的须藤代码,您第一次加载类,然后尝试使用其名称简化您的问题:

defineClass('Tire.class'); 
Tire tire = new Tire(); 

这显然因为轮胎类型不工作是不是可以在编译时:编译器不知道在执行过程中要加载的类型。

工作是让Tire实现一些接口(例如VehiclePart)。所以,那么你可以使用下面的须藤代码:

Class tireClass = defineClass('Tire.class'); 
VehiclePart tire = tireClass.newInstance(); 
System.out.println(tire.getPartName()); // prints 'tire' for example 

那么也许你可以建立你的Drools在接口VehiclePart和getPartName()属性的规则。

附录

以上才有意义,只有当接口包括动态加载的类的所有属性。在大多数情况下,这不是一个有效的解决方案:动态加载的类不会共享属性。所以,这是另一种方法。

而不是使用显式类加载,可以通过'扩展'类加载器类路径来解决此问题。警告,这是一个黑客

在Jodd中,有一种方法:ClassLoaderUtil.addFileToClassPath()可以在运行时向文件或路径添加类加载器。因此,下面是适用于我的步骤:

1)将所有动态创建的类放入某个根文件夹中,并考虑它们的包。例如,假设我们想要使用一个jodd.samples.TestBean类,该类有两个属性:号码(int)和(字符串)。然后我们需要将它放入根目录/ jodd/samples文件夹中。

2)建立的所有动态类之后,扩展类加载器的路径:

ClassLoaderUtil.addFileToClassPath("root", ClassLoader.getSystemClassLoader()); 

3)负载类和创建KnowledgeBuilder之前创建它:

Class testBeanClass = Class.forName("jodd.samples.TestBean"); 
Object testBean = testBeanClass.newInstance(); 

4)在这一点上,你可以使用BeanUtils(来自Jodd,例如:)来操纵testBean实例的属性

5)创建Drools的东西并将insert insert testBean添加到会话中:

knowledgeSession.insert(testBean); 

6)在规则文件中使用它:

import jodd.samples.TestBean; 

rule "xxx" 
    when 
    $t: TestBean(number == 173) 
then 
    System.out.println("!!!"); 
end 

这为我工作。请注意,在第2步中,您可以尝试使用不同的类加载器,但您可能需要通过KnowledgeBuilderConfiguration(即PackageBuilderConfiguration)将它传递到KnowledgeBuilderFactory。

另一种解决方案

另一种解决方案是简单地将所有对象的属性复制到一张地图,及处理规则文件的地图。所以,你可以在步骤4中使用这样的:

Map map = new HashMap(); 
BeanTool.copy(testBean, map); 

及更高版本(步骤#5)添加地图Drools的背景下,而不是bean实例。在这种情况下,使用defineClass()方法来明确定义每个类会更好。

+0

谢谢!我们已经有了一个名为DataType的接口,因此您的解决方案应该非常易于实现。非常感谢你! –

+0

我试过你的解决方案,并收到以下错误消息。我在when子句中定义了这个类,这是正确的还是应该在其他地方? [12,7]:[ERR 102]第12行:在规则“轮胎操作”中,7个不匹配输入'tyreClass'[0,0]:解析器返回null包 –

+0

oops我刚刚意识到你说过sudo代码当然不起作用。对不起 –

相关问题