[JBoss JIRA] Created: (JBRULES-2402) Null Pointer exception while loading and executing two serialized rules which are in same package
by Nagarajan Santhanam (JIRA)
Null Pointer exception while loading and executing two serialized rules which are in same package
-------------------------------------------------------------------------------------------------
Key: JBRULES-2402
URL: https://jira.jboss.org/jira/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: Mark Proctor
Priority: Critical
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("@{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("@{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 contact one of the administrators: https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 2 months
[JBoss JIRA] Created: (JBRULES-2432) TemplateDataListener.newCell filters out correctly blank values; this leads to incorrect template processing
by Denis Robert (JIRA)
TemplateDataListener.newCell filters out correctly blank values; this leads to incorrect template processing
------------------------------------------------------------------------------------------------------------
Key: JBRULES-2432
URL: https://jira.jboss.org/jira/browse/JBRULES-2432
Project: Drools
Issue Type: Bug
Security Level: Public (Everyone can see)
Components: drools-core (expert)
Affects Versions: 5.0.1.FINAL
Environment: Any
Reporter: Denis Robert
Assignee: Mark Proctor
When using a DataProviderCompiler(), a blank column returned by the DataProvider causes an entire line to not be outputted in the result. I tracked this to a line in TemplateDataListener.newCell which explicitly filters out blank cells, even though such cells should be allowed.
The template I'm using is:
<snip>
template header
ruleID
object
field
regexp
replacement
package standardization
import [removed].*
template std_rule
rule "@{ruleID}"
dialect "mvel"
when
$o: @{object}()
then
$o.@{field} = $o.?(a){field}.replaceFirst("@{regexp}", "@{replacement}");
end
end template
<snip>
Whenever "replacement" is blank, the consequent does not get generated.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 2 months
[JBoss JIRA] Created: (JBRULES-2453) Marshalling issue with not rules
by Kris Verlaenen (JIRA)
Marshalling issue with not rules
--------------------------------
Key: JBRULES-2453
URL: https://jira.jboss.org/jira/browse/JBRULES-2453
Project: Drools
Issue Type: Bug
Security Level: Public (Everyone can see)
Components: drools-core (expert)
Affects Versions: 5.1.0.M1
Reporter: Kris Verlaenen
Assignee: Mark Proctor
Fix For: 5.1.0.M2
Issue with OutputMarshaller in specific case of Not rules:
java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2786)
at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:94)
at
java.io.ObjectOutputStream$BlockDataOutputStream.drain(ObjectOutputStream.java:1838)
at
java.io.ObjectOutputStream$BlockDataOutputStream.write(ObjectOutputStream.java:1769)
at java.io.DataOutputStream.writeInt(DataOutputStream.java:182)
at
java.io.ObjectOutputStream$BlockDataOutputStream.writeInt(ObjectOutputStream.java:1904)
at java.io.ObjectOutputStream.writeInt(ObjectOutputStream.java:769)
at
org.drools.marshalling.impl.OutputMarshaller.writeLeftTuple(OutputMarshaller.java:459)
at
org.drools.marshalling.impl.OutputMarshaller.writeInitialFactHandleLeftTuples(OutputMarshaller.java:356)
at
org.drools.marshalling.impl.OutputMarshaller.writeFactHandles(OutputMarshaller.java:251)
at
org.drools.marshalling.impl.OutputMarshaller.writeSession(OutputMarshaller.java:85)
at
org.drools.marshalling.impl.DefaultMarshaller.marshall(DefaultMarshaller.java:117)
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 2 months
[JBoss JIRA] Created: (JBRULES-2463) Deadlock between ResourceChangeNotifierImpl.subscribeResourceChangeListener and ResourceChangeScannerImpl.subscribeNotifier
by Andreas Kohn (JIRA)
Deadlock between ResourceChangeNotifierImpl.subscribeResourceChangeListener and ResourceChangeScannerImpl.subscribeNotifier
---------------------------------------------------------------------------------------------------------------------------
Key: JBRULES-2463
URL: https://jira.jboss.org/jira/browse/JBRULES-2463
Project: Drools
Issue Type: Bug
Security Level: Public (Everyone can see)
Affects Versions: 5.0.1.FINAL
Reporter: Andreas Kohn
Assignee: Mark Proctor
This deadlock was found by our continouos integration system which is building drools using mvn.
Found one Java-level deadlock:
=============================
"Thread-42":
waiting to lock monitor 0x00002aaaf8f2e8d0 (object 0x00002aaab4645830, a java.util.HashMap),
which is held by "main"
"main":
waiting to lock monitor 0x00002aaaf4f3a028 (object 0x00002aaab46459b0, a java.util.HashMap),
which is held by "Thread-42"
Java stack information for the threads listed above:
===================================================
"Thread-42":
at org.drools.io.impl.ResourceChangeNotifierImpl.subscribeResourceChangeListener(ResourceChangeNotifierImpl.java:64)
- waiting to lock <0x00002aaab4645830> (a java.util.HashMap)
at org.drools.io.impl.ResourceChangeNotifierImpl.subscribeChildResource(ResourceChangeNotifierImpl.java:103)
at org.drools.io.impl.ResourceChangeScannerImpl.scan(ResourceChangeScannerImpl.java:128)
- locked <0x00002aaab46459b0> (a java.util.HashMap)
at org.drools.io.impl.ResourceChangeScannerImpl$ProcessChangeSet.run(ResourceChangeScannerImpl.java:276)
- locked <0x00002aaab46459b0> (a java.util.HashMap)
- locked <0x00002aaade2c97d8> (a org.drools.io.impl.ResourceChangeScannerImpl$ProcessChangeSet)
at java.lang.Thread.run(Thread.java:619)
"main":
at org.drools.io.impl.ResourceChangeScannerImpl.subscribeNotifier(ResourceChangeScannerImpl.java:64)
- waiting to lock <0x00002aaab46459b0> (a java.util.HashMap)
at org.drools.io.impl.ResourceChangeNotifierImpl.subscribeResourceChangeListener(ResourceChangeNotifierImpl.java:70)
- locked <0x00002aaab4645830> (a java.util.HashMap)
at org.drools.agent.impl.KnowledgeAgentImpl.processChangeSet(KnowledgeAgentImpl.java:150)
- locked <0x00002aaade2c9c18> (a java.util.HashMap)
at org.drools.agent.impl.KnowledgeAgentImpl.applyChangeSet(KnowledgeAgentImpl.java:117)
- locked <0x00002aaade2c9c18> (a java.util.HashMap)
at org.drools.agent.impl.KnowledgeAgentImpl.applyChangeSet(KnowledgeAgentImpl.java:109)
at org.drools.agent.KnowledgeAgentTest.testModifyDirectory(KnowledgeAgentTest.java:776)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at sun.reflect.GeneratedMethodAccessor44.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.maven.surefire.junit.JUnitTestSet.execute(JUnitTestSet.java:213)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:140)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:127)
at org.apache.maven.surefire.Surefire.run(Surefire.java:177)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:345)
at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:1009)
Found 1 deadlock.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 2 months
[JBoss JIRA] Created: (JBRULES-2457) Wrong evaluation of rules and PseudoClock NPE
by Vítor Moreira (JIRA)
Wrong evaluation of rules and PseudoClock NPE
---------------------------------------------
Key: JBRULES-2457
URL: https://jira.jboss.org/jira/browse/JBRULES-2457
Project: Drools
Issue Type: Bug
Security Level: Public (Everyone can see)
Affects Versions: 5.1.0.M1, 5.0.1.FINAL
Environment: Windows 7, Eclipse 3.4, Java 1.6.0_u18, JUnit 4
Reporter: Vítor Moreira
Assignee: Mark Proctor
I've got a DRL file, having the following rules:
- offline event for 3 minutes withou any online event meanwhile => send an offline notification
- online event after offline event (within 3 minute range) => send an online notification
I've also got an junit test:
- insert offline event
- pseudoclock advances 2m50s
- insert online event
- pseudoclock advances 15s
- check if there's any notification
And the result of the junit is:
1) NPE when clock advances 15s
java.lang.NullPointerException
at org.drools.util.LinkedList.remove(LinkedList.java:113)
at org.drools.common.Scheduler$DuractionJob.execute(Scheduler.java:71)
at org.drools.time.impl.PseudoClockScheduler$ScheduledJob.call(PseudoClockScheduler.java:219)
at org.drools.time.impl.PseudoClockScheduler.runCallBacks(PseudoClockScheduler.java:168)
at org.drools.time.impl.PseudoClockScheduler.advanceTime(PseudoClockScheduler.java:130)
2) When checking for a notification, it should have one online notification but has on offline notification
At the bottom of this issue, there are snippets of junit code and drools rule file.
Probably, the problem relies on Junit initialization code.
T.I.A.
-- DRL file (snippet) --
dialect "java"
declare Event
@role( event )
@expires ( 7d )
end
global ISnmpNotifier snmpNotifier;
/*************************/
/* OFFLINE FOR 3 MINUTES */
/*************************/
rule "bit\dom - events offline (device offline for 3 minutes)"
when
$offline : Event( freeField == "101", $offlineLane : lane ) from entry-point "incoming"
not ( $online : Event (freeField == "102", lane == $offlineLane, this after [0s,3m] $offline ) from entry-point "incoming" )
then
snmpNotifier.send( new Notification("101", "offline") );
end
rule "bit\dom - events online (device offline for 3 minutes)"
when
$offline: Event( freeField == "101", $lane : lane ) from entry-point "incoming"
$online : Event( freeField == "102", lane == $lane, this after [3m] $offline ) from entry-point "incoming"
then
snmpNotifier.send( new Notification("102", "online") );
end
-- DRL file (snippet) --
-- JUnit code (snippet) --
package pt.brisa.sam.agent.rules.bit_dom;
import java.util.concurrent.TimeUnit;
import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseConfiguration;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.conf.EventProcessingOption;
import org.drools.io.ResourceFactory;
import org.drools.runtime.KnowledgeSessionConfiguration;
import org.drools.runtime.StatefulKnowledgeSession;
import org.drools.runtime.conf.ClockTypeOption;
import org.drools.runtime.rule.WorkingMemoryEntryPoint;
import org.drools.time.impl.PseudoClockScheduler;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class Jira_Drools {
// values used to create test
private String offlineEventCode = "101";
private String onlineEventCode = "102";
private String device = "device";
// drools specific vars
private WorkingMemoryEntryPoint workingMemoryEntryPoint;
private PseudoClockScheduler clock = null;
private StatefulKnowledgeSession kSession;
/**
* SnmpNotificationEventCase.getNumberOfNotificationsByExample(example)
* .getNumberOfNotificationsByExample => from the notification queue, returns the number of notifications matching the given example
*/
private SnmpNotificationEventCase snmpNotificationEventCase;
@Before
public void droolsSetup() {
KnowledgeBaseConfiguration baseConfig;
KnowledgeSessionConfiguration sessionConfig;
KnowledgeBase kBase;
KnowledgeBuilder kBuilder;
baseConfig = KnowledgeBaseFactory.newKnowledgeBaseConfiguration();
baseConfig.setOption( EventProcessingOption.STREAM ); // Use stream mode
kBuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kBuilder.add(ResourceFactory.newFileResource( "test.drl"), ResourceType.DRL);
kBase = KnowledgeBaseFactory.newKnowledgeBase(baseConfig);
kBase.addKnowledgePackages(kBuilder.getKnowledgePackages());
sessionConfig = KnowledgeBaseFactory.newKnowledgeSessionConfiguration();
sessionConfig.setOption( ClockTypeOption.get( "pseudo" ) );
kSession = kBase.newStatefulKnowledgeSession( sessionConfig, null );
kSession.setGlobal( "snmpNotifier", snmpNotificationEventCase );
workingMemoryEntryPoint = kSession.getWorkingMemoryEntryPoint("incoming");
clock = (PseudoClockScheduler) kSession.getSessionClock();
snmpNotificationEventCase = new SnmpNotificationEventCase();
}
/* offline online 3min */
/* -----|-------------------|------/----^----- */
/* check */
@Test
public void deviceOffline_onlineBefore3minutes_checkAfter3minutes() {
/* alocates OFFLINE and ONLINE events, EXAMPLE */
Event offlineEvent = new Event();
Event onlineEvent = new Event();
Notification example = new Notification();
/* configures the events */
offlineEvent.setFreeField( offlineEventCode );
offlineEvent.setEventType( (byte)5 );
offlineEvent.setEventCode( "0001000" + offlineEventCode );
offlineEvent.setFormattedMessage( "JUnit string test" );
offlineEvent.setLane( "102" );
onlineEvent.setFreeField( onlineEventCode );
onlineEvent.setEventType( (byte)3 );
onlineEvent.setEventCode( "0001000" + onlineEventCode );
onlineEvent.setFormattedMessage( "JUnit string test" );
onlineEvent.setLane( "102" );
/* insert offline event */
workingMemoryEntryPoint.insert( offlineEvent );
kSession.fireAllRules();
/* intermediary check - offline notification */
example.setRuleCode( "31" );
example.setEventCode( offlineEventCode );
Assert.assertTrue(
"(device "+device+")(ruleCode 31): There are OFFLINE notifications, when it shouldn't have",
snmpNotificationEventCase.getNumberOfNotificationsByExample(example) == 0 );
/* advances the clock */
clock.advanceTime( 2, TimeUnit.MINUTES );
clock.advanceTime( 50, TimeUnit.SECONDS );
/* intermediary check - offline notification */
example.setRuleCode( "31" );
example.setEventCode( offlineEventCode );
Assert.assertTrue(
"(device "+device+")(ruleCode 31): There are OFFLINE notifications, when it shouldn't have",
snmpNotificationEventCase.getNumberOfNotificationsByExample(example) == 0 );
/* insert online event */
workingMemoryEntryPoint.insert( onlineEvent );
kSession.fireAllRules();
/* intermediary check - offline notification */
example.setRuleCode( "31" );
example.setEventCode( offlineEventCode );
Assert.assertTrue(
"(device "+device+")(ruleCode 31): There are OFFLINE notifications, when it shouldn't have",
snmpNotificationEventCase.getNumberOfNotificationsByExample(example) == 0 );
/* intermediary check - online notification */
example.setRuleCode( "31" );
example.setEventCode( onlineEventCode );
Assert.assertTrue(
"(device "+device+")(ruleCode 31): There are ONLINE notifications, when it shouldn't have",
snmpNotificationEventCase.getNumberOfNotificationsByExample(example) == 0 );
/* advances the clock */
clock.advanceTime( 15, TimeUnit.SECONDS );
/* since there's an ONLINE before the 3 minute's limit, there shouldn't be any trap regarding "last offline 3 minutes ago" */
example.setRuleCode( "31" );
example.setEventCode( offlineEventCode );
Assert.assertTrue(
"(device "+device+")(ruleCode 31): There are OFFLINE notifications, when it shouldn't have",
snmpNotificationEventCase.getNumberOfNotificationsByExample(example) == 0 );
example.setRuleCode( "31" );
example.setEventCode( onlineEventCode );
Assert.assertTrue(
"(device "+device+")(ruleCode 31): There are ONLINE notifications, when it shouldn't have",
snmpNotificationEventCase.getNumberOfNotificationsByExample(example) == 1 );
}
}
-- JUnit code (snippet) --
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 2 months
[JBoss JIRA] Created: (JBRULES-2673) There Should be a Relation Between the Fired Rule and the Node which Activates the Ruleflow-Group
by Anatoly Polinsky (JIRA)
There Should be a Relation Between the Fired Rule and the Node which Activates the Ruleflow-Group
-------------------------------------------------------------------------------------------------
Key: JBRULES-2673
URL: https://jira.jboss.org/browse/JBRULES-2673
Project: Drools
Issue Type: Bug
Security Level: Public (Everyone can see)
Affects Versions: 5.1.1.FINAL
Environment: N/A
Reporter: Anatoly Polinsky
Assignee: Mark Proctor
We asked for the following behavior to be implemented:
@Test(expected=NameOfOurLayerOtTopOfDroolsException.class)
public void shouldThrowNameOfOurLayerOtTopOfDroolsExceptionForAnyThrowableThrownWithinDroolsOnTheProcessStart() {
ksession.startProcess("com.jpmc...process-throws-throwable");
}
@Test(expected=NameOfOurLayerOtTopOfDroolsException.class)
public void shouldThrowNameOfOurLayerOtTopOfDroolsExceptionForAnyThrowableThrownWithinDroolsOnTheProcessResume() {
ksession.getWorkItemManager().completeWorkItem( id, null );
}
And Plugtree was prompt to create it for us: http://anonsvn.jboss.org/repos/labs/labs/jbossrules/branches/5_1_20100802...
The only roadblock here, to fulfill our original request, is when Throwable is thrown from within a "ruleflow-group" ( from within rules that are embedded into / invoked from a workflow ), in which case Throwable cannot be caught by the above mechanism due to the fact that:
"At the moment Drools doesn't keep any relation between the fired rule and the node which activates the ruleflow-group, thus if an activated rule blows up there is no way to know which node has made focus on its group"
Since Drools is moving towards having everything under "a single roof/parent of Knowledge", Process and Rule children should be rather siblings than strangers, hence should know a little more about each other.
/Anatoly
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 2 months
[JBoss JIRA] Created: (JBRULES-2650) Stable API should provide Agenda.getActivations()
by Wolfgang Laun (JIRA)
Stable API should provide Agenda.getActivations()
-------------------------------------------------
Key: JBRULES-2650
URL: https://jira.jboss.org/browse/JBRULES-2650
Project: Drools
Issue Type: Feature Request
Security Level: Public (Everyone can see)
Components: drools-api
Affects Versions: 5.1.0.FINAL
Reporter: Wolfgang Laun
Assignee: Mark Proctor
Fix For: 5.1.1.FINAL
The stable API lets you retrieve Agenda from WorkingMemory, and there is an IF for Activation. There should be a
List<Activation> getActivations
in the "stable" Agenda.
This would be highly useful for writing supportive code for inspecting the engine's state at critical points. (I don't see that restricting Agenda views to specific "groups" would be a benefit for such tasks.)
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 2 months