Drools rules is not being fired after 3 times

China☆狼群 提交于 2019-12-24 12:22:56

问题


I have created one knowledge base, then in a loop used knowledge base to create

  • stateless knowledge session
  • and call execute on session, used same data for each iteration.

----- here is main function------

 public static final void main(String[] args)
  {
    KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
    kbuilder.add(ResourceFactory.newClassPathResource("diskRules.drl"), ResourceType.DRL);
    if (kbuilder.hasErrors())
    {

      System.err.println(kbuilder.getErrors().toString());

    }

    KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();

    kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());

    CollectorPluginData cpd = getData();

    for (int i = 0; i < 10; i++)
    {

      System.out.println("Iteration number: " + i);
      StatelessKnowledgeSession ksession = kbase.newStatelessKnowledgeSession();

      ksession.execute(cpd);
    }

---------here is drl file

rule "Disk State: Unconfigured Bad-ERROR"
when
    $diskData : CollectorPluginData(pluginName == "DiskCollectorPlugin", $componentList : componentList)
    $component: Component( type == "Disk"
        && ((properties contains "eventType" && properties["eventType"] == "PD Event" 
              && properties contains "newComponentState"&& properties["newComponentState"] == "Unconfigured Bad") 
            || (properties contains "scsiDeviceType" && properties["scsiDeviceType"] == "Disk" 
              && properties contains "currentComponentState" && properties["currentComponentState"] == "Unconfigured Bad"))
        ) from $componentList  
then

    System.out.println("Rule Fired");
end
rule "Disk State: Unconfigured Bad-OK"
when
    $diskData : CollectorPluginData(pluginName == "DiskCollectorPlugin", $componentList : componentList)
    $component: Component( type == "Disk"
        && ((properties contains "eventType" && properties["eventType"] == "PD Event" 
              && properties contains "newComponentState"&& properties["newComponentState"] != "Unconfigured Bad") 
            || (properties contains "scsiDeviceType" && properties["scsiDeviceType"] == "Disk" 
              && properties contains "currentComponentState" && properties["currentComponentState"] != "Unconfigured Bad"))
        ) from $componentList  
then

    System.out.println("Rule Fired");
end

As for each iteration same data is used to execute session, so same set of rules is expected to be executed, but i observed after some iteration no rule is getting triggered.

Here is a console output for each iteration:

Iteration number: 0
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Iteration number: 1
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Iteration number: 2
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Rule Fired
Iteration number: 3
Iteration number: 4
Iteration number: 5
Iteration number: 6
Iteration number: 7
Iteration number: 8
Iteration number: 9

some observations:

  • In each rule i have $componentList for matching, when we reduce the number of components in component list then it takes more iterations to reach situation where no rule gets triggered.

  • when we change the condition in rule file to simple(mentioned below) then every iteration generates same output.

    $component: Component( type == "Disk") from $componentList

This looks like a issue with drools, some kind of memory or data structure corruption.

I have tried with statefull session as well and saw same behavior.

Am i missing something here? my understanding is knowledge base is kind of readonly we can create any number of sessions from it.

here 5.6.0.Final version is being used, have tried with drools 6.1.0 as well but saw same behavior.

I am stuck due to this issue, will appreciate any help.

In case u want to reproduce this issue following class definitions will help

MainClass.java
    package com.test
    import com.test.CollectorPluginData;
    import com.test.Component;

    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;

    import org.drools.KnowledgeBase;
    import org.drools.KnowledgeBaseFactory;
    import org.drools.builder.KnowledgeBuilder;
    import org.drools.builder.KnowledgeBuilderFactory;
    import org.drools.builder.ResourceType;
    import org.drools.io.ResourceFactory;
    import org.drools.runtime.StatelessKnowledgeSession;

    public class MainClass
    {
      public static final void main(String[] args)
      {
        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        kbuilder.add(ResourceFactory.newClassPathResource("diskRules.drl"), ResourceType.DRL);
        if (kbuilder.hasErrors())
        {

          System.err.println(kbuilder.getErrors().toString());

        }

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();

        kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());

        CollectorPluginData cpd = getData();

        for (int i = 0; i < 10; i++)
        {

          System.out.println("Iteration number: " + i);
          StatelessKnowledgeSession ksession = kbase.newStatelessKnowledgeSession();

          ksession.execute(cpd);
        }
      }

      public static CollectorPluginData getData()
      {

        CollectorPluginData cpd = new CollectorPluginData();

        cpd.setPluginName("DiskCollectorPlugin");

        List<Component> components = getDiskComponets("Online", 5);
        components.addAll(getDiskComponets("Unconfigured Good", 5));
        components.addAll(getDiskComponets("Unconfigured Bad", 5));
        components.addAll(getDiskComponets("Offline", 5));
        components.addAll(getDiskComponets("Failed", 5));
        cpd.setComponentList(components);

        return cpd;

      }

      private static List<Component> getDiskComponets(String status, int num)
      {
        List<Component> components = new ArrayList<Component>();
        int enclosure = new Random().nextInt();
        for (int i = 0; i < num; i++)
        {
          Component c = new Component();
          c.setType("Disk");
          c.setName("Enclosure " + enclosure + " Disk " + String.valueOf(i + 1));
          c.setId(enclosure + "_" + String.valueOf(i + 1));
          c.setproperty("isSupported", 1);
          c.setproperty("pdMediaType", "Rotating Media, HDD");
          c.setproperty("mediaErrorCount", 0);
          c.setproperty("scsiDeviceType", "Disk");
          c.setproperty("lastFailedPredEventSeqNum", 0);
          c.setproperty("currentComponentState", status);
          c.setproperty("otherErrorCount", 0);
          c.setproperty("isGlobalHotSpare", 0);
          c.setproperty("isForcedPdGuid", 0);
          c.setproperty("maxSupportedSpeed", "6G");
          c.setproperty("isDedicatedHotSpare", 0);
          c.setproperty("isForeign", 0);
          c.setproperty("predFailCount", 0);
          c.setproperty("driveReadyForRemoval", 0);
          c.setproperty("linkSpeed", 3);
          c.setproperty("isPdInVd", 0);
          c.setproperty("pdDeviceType", "SAS");
          c.setproperty("rawSize", 1953525168);
          c.setproperty("enclosureId", 252);
          c.setproperty("nonCoercedSize", 1952476592);
          c.setproperty("coercedSize", 1951170560);
          c.setproperty("temperatureInCelsius", 255);
          c.setproperty("slotNumber", 2);
          c.setproperty("pdPowerState", "Spun Down");
          c.setproperty("shieldCounter", 0);
          c.setproperty("shieldDiagCompletionTime", "0000-00-00T00:00:00");
          components.add(c);
        }
        return components;
      }
    }

Component.java

 package com.test;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;

import java.util.HashMap;
import java.util.Map;

public class Component
{
  protected String type;
  protected String id; 
  protected String name; 

  protected Map<String, Object> properties;

  public String getType()
  {
    return type;
  }

  public void setType(String type)
  {
    this.type = type;
  }

  public Map<String, Object> getProperties()
  {
    return properties;
  }

  public void setProperties(Map<String, Object> properties)
  {
    this.properties = properties;
  }

  public void setproperty(String key, Object value)
  {
    if (this.properties == null)
    {
      this.properties = new HashMap<String, Object>();
    }

    this.properties.put(key, value);

  }

  public Component()
  {
    super();

  }

  public Component(String type, String id, int status)
  {

    this.type = type;
    this.id = id;
    setproperty("status", status);

  }

  public String getId()
  {
    return id;
  }

  public void setId(String id)
  {
    this.id = id;
  }

  public String getName()
  {
    return name;
  }

  public void setName(String name)
  {
    this.name = name;
  }

}

CollectorPluginData.java

package com.test;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;

import java.util.ArrayList;
import java.util.List;

public class CollectorPluginData
{
  private String pluginName;
  private String timeStamp;
  private String hostName;
  private String serialNumber;
  private String model;
  private List<Component> componentList;

  public String getSerialNumber()
  {
    return serialNumber;
  }

  public void setSerialNumber(String serialNumber)
  {
    this.serialNumber = serialNumber;
  }

  public String getModel()
  {
    return model;
  }

  public void setModel(String model)
  {
    this.model = model;
  }

  public String getHostName()
  {
    return hostName;
  }

  public void setHostName(String hostName)
  {
    this.hostName = hostName;
  }

  public String getPluginName()
  {
    return pluginName;
  }

  public void setPluginName(String pluginName)
  {
    this.pluginName = pluginName;
  }

  public String getTimeStamp()
  {
    return timeStamp;
  }

  public void setTimeStamp(String timeStamp)
  {
    this.timeStamp = timeStamp;
  }

  public List<Component> getComponentList()
  {
    return componentList;
  }

  public void setComponentList(List<Component> componentList)
  {
    this.componentList = componentList;
  }

  public void addComponent(Component component)
  {
    if (componentList == null)
    {
      componentList = new ArrayList<Component>();
    }
    componentList.add(component);
  }
}

回答1:


It is indeed a bug. The problem is in the use of "contains" : Drools (MVEL) is very liberal in assuming that properties contains "X" should be interpreted as properties.containsKey("X"). After some iterations, though, the just-in-time compilation of the constraints enforces a stricter mode, where the former expression can't be evaluated correctly. We'll discuss what the best fix is. In any case, I'd recommend to use properties.containsKey... or maybe even remove the contains check, since the map accessor will just return null when the key is not present.



来源:https://stackoverflow.com/questions/27852305/drools-rules-is-not-being-fired-after-3-times

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!