I've used KIE component and drools rule to create calculating-rule of shipping products. I defined my rule in *.drl as following:
My *.drl
file:
package shipment.orderrate;
dialect "mvel"
import org.mag.erp.model.Product
function Double calculateVolume(Double height, Double width, Double depth){
if(height == null || width == null || depth == null){
return 0d;
}
if(height == -1 || width == -1 || depth == -1){
return 0d;
}
return height * width * depth;
}
rule "Calculate Shipping_by_volumne"
when
$p: Product(calculateVolume(height, width, depth) >= 0.0, calculateVolume(height, width, depth) < 100.0, shippingTotal == null
then
modify($p){
setShippingTotal(80000.0)
};
end
The java file class Product.java
is located in my component with source code:
package org.mag.erp.model;
import java.io.Serializable;
public class Product implements Serializable {
private String productId;
private Double height;
private Double width;
private Double weight;
private Double depth;
private Double shippingTotal;
//*getter and setter property*
}
When I started moqui, it giving me this error:
00:06:57.151 ERROR main o.drools.c.k.b.i.KieProject Unable to build KieBaseModel:MagOrderShippingRateKB
Unable to resolve ObjectType 'Product' : [Rule name='Calculate Shipping_by_volumne']
Unable to Analyse Expression @Modify with($p){ setShippingTotal(80000.0) };:
[Error: unable to resolve method using strict-mode: org.drools.core.spi.KnowledgeHelper.$p()]
But if I move Product.java
file to org.moqui.util
package in moqui-util
component and edit import org.mag.erp.model.Product
to import org.moqui.util.Product
in my *.drl
file, moqui will start normally and have no error.
Why this happen? What is the special config in moqui-util
that make KieBase
build with no error when I put Product.java
into this component?
This looks like a ClassLoader issue. In order to support runtime additions to the classpath Moqui uses a custom ClassLoader that supports this behavior, including the 'classes' and 'lib' directories under the 'runtime' directory or in component directories. The custom ClassLoader (MClassLoader) is set as the context ClassLoader for each thread within the servlet container or threads created internally for Moqui background jobs, etc.
The most likely reason this happens with KIE 'mvel' scripts is that it does not use the current thread's context ClassLoader (ie the mvel compiler isn't using it) or it is running in a thread not initialized through Moqui Framework so the thread's context ClassLoader is not set yet.
The first step to fix this would be to research classloading options for the mvel compiler. There may be a file where it is configured but it is more likely an API option that is needed, perhaps to specify the ClassLoader explicitly so it uses the thread's context ClassLoader. If you want help pursuing that it isn't really a question any more and doesn't belong on StackOverflow. The Moqui community collaboration resources available are described on the Moqui web site here: