Search code examples
javadroolsrules

I want to compare two lists using drools, but the rules are not firing


After inserting two arraylists of type InboundRegionalProduct and ExistingRegionalProduct in to the drools session the rules are not getting fired. Don't know whats the issue is. This is the drl file.

package rules;
import com.ferguson.mw.k8.pricing.b2ccontroller.model.InboundRegionalProduct;
import com.ferguson.mw.k8.pricing.b2ccontroller.model.ExistingRegionalProduct;
dialect "java"

rule "Exists, no change in flag"
 when
 $in : InboundRegionalProduct();
 $existing : ExistingRegionalProduct(productId == $in.productId, regionallyPriced == $in.regionallyPriced);
then
 delete($in);
 delete($existing);
end
// Match based on prodcutId and regionallyPriced flags are different from one another.
query "delta"
 $in : InboundRegionalProduct();
 ExistingRegionalProduct(productId == $in.productId);
end
// Inbound but no existing product. The regionallyPriced attribute must be set to "true" 
query "add"
 $in : InboundRegionalProduct();
 not ExistingRegionalProduct(productId == $in.productId);
end
// Match based on having an existing product with a flag and no matching inbound product. The regionallyPriced attribute should be removed for these.
query "remove"
$existing : ExistingRegionalProduct()
not InboundRegionalProduct(productId == $existing.productId)
end

The pojo classes are below;

@Data
@AllArgsConstructor
public abstract class RegionalProduct {
private final String productId;
private final Boolean regionallyPriced;
}



@Data
@EqualsAndHashCode(callSuper = true)
public class InboundRegionalProduct extends RegionalProduct {
public InboundRegionalProduct(final String productId) {
super(productId, Boolean.TRUE);
}
}



@Data
@EqualsAndHashCode(callSuper = true)
public class ExistingRegionalProduct extends RegionalProduct {
public ExistingRegionalProduct(final String productId, final Boolean regionallyPriced) {
super(productId, regionallyPriced);
}
}

Solution

  • As you said, you are inserting the lists, but not the individual objects as facts. Your rules are written for individual facts. So you either insert each element inside your lists in the session, or you create a rule that does that for you:

    rule "Insert List elements"
    when
        $l: List()
        $p: RegionalProduct() from $l
    then
        insert($p);
    end
    

    Another option would be to include the List extraction part in your existing rules. For example:

    rule "Exists, no change in flag"
     when
     $l: List()
     $in : InboundRegionalProduct() from $l
     $existing : ExistingRegionalProduct(productId == $in.productId, regionallyPriced == $in.regionallyPriced) from $l;
    then
     delete($in);
     delete($existing);
    end
    

    The problem with including the List in your DRL though is that it can get messy if you start having different Lists with different meanings. In that case, you can either create your own Object wrapper of a specific type containing a List and then write the rules about those Objects.

    My suggestion: just insert each individual fact in your session from you Java code.