]
Geoffrey De Smet updated JBRULES-2402:
--------------------------------------
Fix Version/s: 5.4.0.Beta3
(was: 5.4.0.Beta2)
Null Pointer exception while loading and executing two serialized
rules which are in same package
-------------------------------------------------------------------------------------------------
Key: JBRULES-2402
URL:
https://issues.jboss.org/browse/JBRULES-2402
Project: Drools
Issue Type: Bug
Security Level: Public(Everyone can see)
Components: drools-core (expert)
Affects Versions: 5.0.1.FINAL
Environment: OS : Ubuntu ( 2.6.28-13-server )
Sun Jdk 1.3
Reporter: Nagarajan Santhanam
Assignee: Tihomir Surdilovic
Priority: Critical
Fix For: 5.4.0.Beta3
Hi,
I'm trying to load drts in a serialized fashion and executing it. During execution, I
get the error as mentioned below.
But if I keep the package name different for both the drts, the same code works fine.
Find below the errors and code snippets :
Files Used :
1. Main.java
2. SchemeEngine.java
3. PurchaseOrder.java
4. PurchaseOrderImpl.java
5. SchemeHelper.java
6. ON_PO_PROD_PACK_PER_DISC.drt
7. ON_PO_PROD_DIS.drt
Main.java
*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package test;
import app.PurchaseOrder;
import app.PurchaseOrderImpl;
import java.util.ArrayList;
import java.util.List;
import scheme.SchemeEngine;
/**
*
* @author msuser1
*/
public class Main {
/**
* @param args the command line arguments
*/
public static void testCrazyBug() throws Exception {
// String[] drts = new String[]{"/ON_PO_PROD_DIS.drt",
"/ON_PO_PROD_PACK_PER_DISC.drt",
"/ON_PO_PROD_PACK_PER_DISC_using_function.drt"};
// String[] xls = new String[]{"/ON_PO_PROD_DISC_1.xls",
"/ON_PO_PROD_PACK_PER_DISC.xls",
"/ON_PO_PROD_PACK_PER_DISC_using_function.xls"};
String[] drts = new String[]{"/ON_PO_PROD_DIS.drt",
"/ON_PO_PROD_PACK_PER_DISC.drt"};
String[] xls = new String[]{"/ON_PO_PROD_DISC_1.xls",
"/ON_PO_PROD_PACK_PER_DISC.xls"};
PurchaseOrder po = new PurchaseOrderImpl();
System.out.println("length of drt " + drts.length);
SchemeEngine engineDirect = new
SchemeEngine(PurchaseOrderImpl.class.getClassLoader());
for (int i = 0; i < drts.length; i++) {
engineDirect.loadSchemeFromDRT(drts[i], xls[i]);
}
System.out.println("Applying Schemes in normal mode");
engineDirect.applyOnPurchaseOrder(po);
List serializedList = new ArrayList();
for (int i = 0; i < drts.length; i++) {
SchemeEngine engineLocal = new
SchemeEngine(PurchaseOrderImpl.class.getClassLoader());
engineLocal.loadSchemeFromDRT(drts[i], xls[i]);
byte[] blobBytes = engineLocal.serializeDefinition();
serializedList.add(blobBytes);
}
SchemeEngine engineOptimized = new
SchemeEngine(PurchaseOrderImpl.class.getClassLoader());
for (int i = 0; i < drts.length; i++) {
engineOptimized.loadSerializedDefinition((byte[]) serializedList.get(i));
}
try {
System.out.println("Applying Schemes in optmized mode");
engineOptimized.applyOnPurchaseOrder(po);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) throws Exception {
testCrazyBug();
}
}
SchemeEngine.java
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package scheme;
import app.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseConfiguration;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.DecisionTableConfiguration;
import org.drools.builder.DecisionTableInputType;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.common.DroolsObjectInputStream;
import org.drools.common.DroolsObjectOutputStream;
import org.drools.decisiontable.ExternalSpreadsheetCompiler;
import org.drools.decisiontable.InputType;
import org.drools.definition.KnowledgePackage;
import org.drools.io.ResourceFactory;
import org.drools.runtime.StatelessKnowledgeSession;
import org.drools.template.parser.DataListener;
import org.drools.template.parser.TemplateDataListener;
/**
*
* @author msuser1
*/
public class SchemeEngine {
private KnowledgeBase kbase = null;
private ClassLoader classLoader = null;
public SchemeEngine(ClassLoader cl) {
this.classLoader = cl;
KnowledgeBaseConfiguration kbc =
KnowledgeBaseFactory.newKnowledgeBaseConfiguration(new Properties(), this.classLoader);
kbase = KnowledgeBaseFactory.newKnowledgeBase(kbc);
}
public void loadSchemeFromDRL(String drlFileName) {
DecisionTableConfiguration dtableconfiguration =
KnowledgeBuilderFactory.newDecisionTableConfiguration();
dtableconfiguration.setInputType(DecisionTableInputType.XLS);
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource(drlFileName,
SchemeEngine.class),
ResourceType.DRL);
if (kbuilder.hasErrors()) {
System.err.println(kbuilder.getErrors().toString());
}
kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
}
public void loadSchemeFromXLS(String xlsFileName) {
DecisionTableConfiguration dtableconfiguration =
KnowledgeBuilderFactory.newDecisionTableConfiguration();
dtableconfiguration.setInputType(DecisionTableInputType.XLS);
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource(xlsFileName,
SchemeEngine.class),
ResourceType.DTABLE, dtableconfiguration);
if (kbuilder.hasErrors()) {
System.err.println(kbuilder.getErrors().toString());
}
kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
}
public void loadSchemeFromDRT(String drtFileName, String xlsFileName) throws
Exception {
loadSchemeFromDRT(drtFileName, xlsFileName, 1, 1);
}
public void loadSchemeFromDRT(String drtFileName, String xlsFileName, int
startingRow, int startingColumn) throws Exception {
InputStream drtInput = SchemeEngine.class.getResourceAsStream(drtFileName);
ByteArrayOutputStream drtOut = new ByteArrayOutputStream();
writeToStream(drtInput, drtOut);
InputStream xlsInput = SchemeEngine.class.getResourceAsStream(xlsFileName);
ByteArrayOutputStream xlsOut = new ByteArrayOutputStream();
writeToStream(xlsInput, xlsOut);
loadSchemeFromDRT(drtOut.toByteArray(), xlsOut.toByteArray(), startingRow,
startingColumn);
}
private void writeToStream(InputStream in, OutputStream out) throws IOException {
byte[] buf = new byte[4 * 1024];
int numRead = 0;
while ((numRead = in.read(buf)) >= 0) {
out.write(buf, 0, numRead);
}
}
public void loadSchemeFromDRT(byte[] drtContent, byte[] xlsContent) {
loadSchemeFromDRT(drtContent, xlsContent, 1, 1);
}
public void loadSchemeFromDRT(byte[] drtContent, byte[] xlsContent, int startingRow,
int startingColumn) {
final ExternalSpreadsheetCompiler converter = new ExternalSpreadsheetCompiler();
final List<DataListener> listeners = new ArrayList<DataListener>();
InputStream in = new ByteArrayInputStream(drtContent);
TemplateDataListener listener = new TemplateDataListener(3, 1, in);
listeners.add(listener);
converter.compile(new ByteArrayInputStream(xlsContent), InputType.XLS,
listeners);
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newByteArrayResource(listener.renderDRL().getBytes()),
ResourceType.DRL);
if (kbuilder.hasErrors()) {
System.err.println(kbuilder.getErrors().toString());
}
kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
}
public byte[] serializeDefinition() {
DroolsObjectOutputStream dos = null;
ByteArrayOutputStream bos = null;
try {
bos = new ByteArrayOutputStream();
dos = new DroolsObjectOutputStream(bos);
dos.writeObject(kbase.getKnowledgePackages());
return bos.toByteArray();
} catch (IOException ex) {
Logger.getLogger(SchemeEngine.class.getName()).log(Level.SEVERE, null, ex);
return null;
} finally {
try {
dos.close();
bos.close();
} catch (IOException ex) {
Logger.getLogger(SchemeEngine.class.getName()).log(Level.SEVERE, null,
ex);
}
}
}
public void loadSerializedDefinition(byte[] serializedContent) {
try {
DroolsObjectInputStream dis = null;
ByteArrayInputStream bis = null;
bis = new ByteArrayInputStream(serializedContent);
dis = new DroolsObjectInputStream(bis);
Collection<KnowledgePackage> defn =
(Collection<KnowledgePackage>)dis.readObject();
kbase.addKnowledgePackages(defn);
} catch (ClassNotFoundException ex) {
Logger.getLogger(SchemeEngine.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(SchemeEngine.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void applyOnPurchaseOrder(PurchaseOrder purchaseOrder) {
if (kbase.getKnowledgePackages().size() == 0) {
throw new RuntimeException("No Schemes are loaded.");
}
List objects = new ArrayList();
objects.add(purchaseOrder);
if (purchaseOrder.orderDetails() != null &&
purchaseOrder.orderDetails().size() > 0) {
Iterator iter = purchaseOrder.orderDetails().iterator();
while (iter.hasNext()) {
PurchaseOrderDetail detail = (PurchaseOrderDetail) iter.next();
objects.add(detail);
}
}
StatelessKnowledgeSession session = kbase.newStatelessKnowledgeSession();
session.execute(Arrays.asList(objects.toArray()));
}
public void applyRule(Object[] objects) {
if (kbase.getKnowledgePackages().size() == 0) {
throw new RuntimeException("No Schemes are loaded.");
}
StatelessKnowledgeSession session = kbase.newStatelessKnowledgeSession();
session.execute(Arrays.asList(objects));
}
public static void main(String[] args) {
}
}
PurchaseOrder.java
package app;
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
import java.util.Date;
import java.util.List;
/**
*
* @author msuser1
*/
public interface PurchaseOrder {
public Float orderAmount();
public Date orderDate();
public Integer orderDay();
public List orderDetails();
public boolean belongsToGeoHierarchy(String nodeName);
public void addFreeItem(String schemeId, String skuId, int qty);
public void addFlatDiscount(String SchemeId, Float discountAmt);
public void addPercentageDiscount(String SchemeId, Float discountPercent);
public void addFlatDiscountForItem(String SchemeId, String skuId, Float
discountAmt);
public void addPercentageDiscountForItem(String SchemeId, String skuId, Float
discountPercent);
public void addPercentageDiscountPerUomForItem(String SchemeId, String skuId, Float
discountPercent);
public void addInternalGiftVoucher(String SchemeId, Float voucherAmt);
public void addExternalGiftVoucher(String SchemeId, Float voucherAmt, String
externalVendorId);
public void addInternalGiftVoucherForItem(String SchemeId, String skuId, Float
voucherAmt);
public void addExternalGiftVoucherForItem(String SchemeId, String skuId, Float
voucherAmt, String externalVendorId);
public void addRewardPoint(String SchemeId, int rewardPoint);
public void addRewardPointForItem(String SchemeId, String skuId, int rewardPoint);
public void addWeightBasedFlatDiscountPerUomForItem(String SchemeId, String skuId,
Float discount_amt, String uomId);
public Boolean immediatePayment();
public Boolean regularPurchase();
public Boolean consignmentPurchase();
public Boolean cat2ConsignmentPurchase();
public Boolean cat3ConsignmentPurchase();
public Boolean intransitPurchase();
public Boolean skuPresent(String skuId);
public Integer materialQuantityForItem(String skuId);
public Boolean schemeApplied(String schemeDefinitionId);
public void addDetail(PurchaseOrderDetail prd);
}
=========================================================================================================================
PurchaseOrderImpl.java
package app;
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author msuser1
*/
public class PurchaseOrderImpl implements PurchaseOrder {
private List details = new ArrayList();
public Date orderDate() {
try {
DateFormat fmt = new SimpleDateFormat("yyyy-dd-MM");
Date dt = fmt.parse("2009-06-23");
return dt;
} catch (ParseException ex) {
Logger.getLogger(PurchaseOrderImpl.class.getName()).log(Level.SEVERE, null,
ex);
return null;
}
}
public Integer orderDay(){
return 10;
}
public List orderDetails() {
return details;
}
public boolean belongsToGeoHierarchy(String nodeName) {
return true;
}
public void addFreeItem(String schemeId, String skuId, int qty) {
System.out.println("Add Free Item");
}
public void addFlatDiscount(String SchemeId, Long discountAmt) {
System.out.println("Add Flat Discount");
}
public void addPercentageDiscount(String SchemeId, int discountPercent) {
System.out.println("Add Percentage Discount");
}
public void addFlatDiscountForItem(String SchemeId, String skuId, Long discountAmt)
{
System.out.println("Add Flat Discount For Item");
}
public void addPercentageDiscountForItem(String SchemeId, String skuId, int
discountPercent) {
System.out.println("Add Percentage Discount For Item");
}
public void addPercentageDiscountPerUomForItem(String SchemeId, String skuId, int
discountPercent) {
System.out.println("Add Percentage Discount For Uom For Item");
}
public void addInternalGiftVoucher(String SchemeId, Long voucherAmt) {
System.out.println("Add Internal Gift Voucher");
}
public void addExternalGiftVoucher(String SchemeId, Long voucherAmt, String
externalVendorId) {
System.out.println("Add External Gift Voucher");
}
public void addInternalGiftVoucherForItem(String SchemeId, String skuId, Long
voucherAmt) {
System.out.println("Add Internal Gift Voucher For Item");
}
public void addExternalGiftVoucherForItem(String SchemeId, String skuId, Long
voucherAmt, String externalVendorId) {
System.out.println("Add External Gift Voucher For Item");
}
public void addRewardPoint(String SchemeId, int rewardPoint) {
System.out.println("Add Reward Point");
}
public void addRewardPointForItem(String SchemeId, String skuId, int rewardPoint) {
System.out.println("Add Reward Point For Item");
}
public Boolean immediatePayment(){
return true;
}
public Boolean regularPurchase() {
return true;
}
public Boolean consignmentPurchase() {
return false;
}
public Boolean cat2ConsignmentPurchase() {
return false;
}
public Boolean cat3ConsignmentPurchase() {
return false;
}
public Boolean commissionPurchase() {
return false;
}
public Boolean intransitPurchase() {
return false;
}
public Boolean skuPresent(String skuId) {
return false;
}
public Integer materialQuantityForItem(String skuId) {
return 10;
}
public Boolean schemeApplied(String schemeDefinitionId) {
return false;
}
public void addWeightBasedFlatDiscountPerUomForItem(String SchemeId, String skuId,
Long discount_amt, String uomId) {
throw new UnsupportedOperationException("Not supported yet.");
}
public void addDetail(PurchaseOrderDetail pod)
{
details.add(pod);
}
public void addFlatDiscount(String SchemeId, Float discountAmt) {
throw new UnsupportedOperationException("Not supported yet.");
}
public void addFlatDiscountForItem(String SchemeId, String skuId, Float discountAmt)
{
throw new UnsupportedOperationException("Not supported yet.");
}
public Float orderAmount() {
throw new UnsupportedOperationException("Not supported yet.");
}
public void addPercentageDiscount(String SchemeId, Float discountPercent) {
throw new UnsupportedOperationException("Not supported yet.");
}
public void addPercentageDiscountForItem(String SchemeId, String skuId, Float
discountPercent) {
throw new UnsupportedOperationException("Not supported yet.");
}
public void addPercentageDiscountPerUomForItem(String SchemeId, String skuId, Float
discountPercent) {
throw new UnsupportedOperationException("Not supported yet.");
}
public void addInternalGiftVoucher(String SchemeId, Float voucherAmt) {
throw new UnsupportedOperationException("Not supported yet.");
}
public void addExternalGiftVoucher(String SchemeId, Float voucherAmt, String
externalVendorId) {
throw new UnsupportedOperationException("Not supported yet.");
}
public void addInternalGiftVoucherForItem(String SchemeId, String skuId, Float
voucherAmt) {
throw new UnsupportedOperationException("Not supported yet.");
}
public void addExternalGiftVoucherForItem(String SchemeId, String skuId, Float
voucherAmt, String externalVendorId) {
throw new UnsupportedOperationException("Not supported yet.");
}
public void addWeightBasedFlatDiscountPerUomForItem(String SchemeId, String skuId,
Float discount_amt, String uomId) {
throw new UnsupportedOperationException("Not supported yet.");
}
}
SchemeHelper.java
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package helper;
import app.PurchaseOrder;
import app.PurchaseOrderDetail;
import java.lang.Float;
/**
*
* @author msuser1
*/
public class SchemeHelper {
public static boolean belongsToProductHierarchy(String skuId, String nodeName) {
return false; //Sku.belongsToProductHierarchy(nodeName);
}
public static Integer materialQuantityForItem(PurchaseOrder po, String skuId) {
return po.materialQuantityForItem(skuId);
}
public static boolean productIdOrProductAncestorMatching(PurchaseOrderDetail
poDetail, String productId) {
System.out.println("Inside the
method......................################################");
boolean result = false;
try {
result = poDetail.productId().compareTo(productId) == 0 ||
poDetail.belongsToAncestorProduct(productId).booleanValue();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public static boolean complexMethod(PurchaseOrderDetail poDetail, String productId,
String packId) {
boolean result = false;
try {
result = (poDetail.packId().compareTo(packId) == 0 ||
poDetail.belongsToAncestorPack(packId).booleanValue()) &&
(poDetail.productId().compareTo(productId) == 0 ||
poDetail.belongsToAncestorProduct(productId).booleanValue());
} catch (Exception ex) {
ex.printStackTrace();
}
return result;
}
}
ON_PO_PROD_DIS.drt
template header
SchemeID
ProductID
Discount
package app;
import function helper.SchemeHelper.*
template "Scheme"
rule "po_@{SchemeID}_(a){row.rowNumber}"
when
$order : PurchaseOrder()
$orderDetail : PurchaseOrderDetail($det :
this,eval($det.productId().compareTo("@{ProductID}") == 0 ||
$det.belongsToAncestorProduct("@{ProductID}") == true), purchaseOrder ==
$order)
then
float disAmt=0;
disAmt = $orderDetail.saleableQty() * @{Discount}F;
System.out.println("Discount amount = @{Discount}..XXXX..........." +
disAmt);
$order.addFlatDiscountForItem("(a){SchemeID}",$orderDetail.skuId(), disAmt);
end
end template
ON_PO_PROD_PACK_PER_DISC.drt
template header
SchemeID
ProductID
PackID
Discount
package app;
import app.*;
import function helper.SchemeHelper.*
template "Scheme"
rule "ON_PO_PROD_PACK_PER_DISC_(a){row.rowNumber}"
when
$order: PurchaseOrder()
$orderDetail : PurchaseOrderDetail($det : this, eval(
($det.belongsToAncestorPack("@{PackID}") == true ||
$det.packId().compareTo("@{PackID}") == 0)
&&
($det.productId().compareTo("@{ProductID}") == 0 ||
$det.belongsToAncestorProduct("@{ProductID}") == true)
) , purchaseOrder == $order)
then
float disAmt=0;
disAmt = ($orderDetail.materialPrice() * $orderDetail.saleableQty()) *
@{Discount}F/100;
System.out.println("Discount amount = XXXX..........." + disAmt);
$order.addFlatDiscountForItem("(a){SchemeID}",$orderDetail.skuId(), disAmt);
end
end template
Error :
java.lang.NullPointerException
at org.drools.base.ClassFieldReader.getIndex(ClassFieldReader.java:78)
at
org.drools.util.LeftTupleIndexHashTable.<init>(LeftTupleIndexHashTable.java:48)
at
org.drools.util.LeftTupleIndexHashTable.<init>(LeftTupleIndexHashTable.java:35)
at
org.drools.common.SingleBetaConstraints.createBetaMemory(SingleBetaConstraints.java:172)
at org.drools.reteoo.BetaNode.createMemory(BetaNode.java:340)
at
org.drools.common.ConcurrentNodeMemories.createNodeMemory(ConcurrentNodeMemories.java:96)
at
org.drools.common.ConcurrentNodeMemories.getNodeMemory(ConcurrentNodeMemories.java:75)
at
org.drools.common.AbstractWorkingMemory.getNodeMemory(AbstractWorkingMemory.java:1534)
at org.drools.reteoo.JoinNode.assertLeftTuple(JoinNode.java:103)
at
org.drools.reteoo.CompositeLeftTupleSinkAdapter.doPropagateAssertLeftTuple(CompositeLeftTupleSinkAdapter.java:145)
at
org.drools.reteoo.CompositeLeftTupleSinkAdapter.createAndPropagateAssertLeftTuple(CompositeLeftTupleSinkAdapter.java:57)
at
org.drools.reteoo.LeftInputAdapterNode.assertObject(LeftInputAdapterNode.java:142)
at
org.drools.reteoo.SingleObjectSinkAdapter.propagateAssertObject(SingleObjectSinkAdapter.java:42)
at org.drools.reteoo.ObjectTypeNode.assertObject(ObjectTypeNode.java:185)
at org.drools.reteoo.EntryPointNode.assertObject(EntryPointNode.java:146)
at
org.drools.common.AbstractWorkingMemory.insert(AbstractWorkingMemory.java:1046)
at
org.drools.common.AbstractWorkingMemory.insert(AbstractWorkingMemory.java:1001)
at
org.drools.common.AbstractWorkingMemory.insert(AbstractWorkingMemory.java:788)
at
org.drools.impl.StatelessKnowledgeSessionImpl.execute(StatelessKnowledgeSessionImpl.java:259)
at scheme.SchemeEngine.applyOnPurchaseOrder(SchemeEngine.java:178)
at test.Main.testCrazyBug(Main.java:55)
at test.Main.main(Main.java:64)
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: