简体   繁体   中英

how to correctly fire Drools rules on multiple objects?

i'm getting my hands on Drools ( with java ) for the first time and i'm quite confused about it's sessions and ability to work with collections of objects. this is the case:

i'm building a web-application made of rest-services.

i have a class called Log with two fields ( eventType and RiskLevelId ).

Mycode retrieves from a db several objects of this kind in a defined time frame.

If this collection of objects happens to contain one Log with eventType == 2 and RiskLevelId == 1 and another Log with eventType == 3 and RiskLevelId == 1, the rule should be executed.

Via Drools interfaces I correctly retrieve KieServices, KieBuilder, KieContaier, KieBase and KieSession.

try {
        // load up the knowledge base
        KieServices kieServices = KieServices.Factory.get();
        KieFileSystem kfs = kieServices.newKieFileSystem();
        FileInputStream fis = f;
        kfs.write( "src/main/resources/simple.drl",
                kieServices.getResources().newInputStreamResource( fis ) );
        KieBuilder kieBuilder = kieServices.newKieBuilder( kfs ).buildAll();
        Results results = kieBuilder.getResults();
        if( results.hasMessages( Message.Level.ERROR ) ){
            System.out.println( results.getMessages() );
            throw new IllegalStateException( "### errors ###" );
        }
        KieContainer kieContainer = kieServices.newKieContainer( kieServices.getRepository().getDefaultReleaseId() );
        KieBase kieBase = kieContainer.getKieBase();
        kieSession = kieContainer.newKieSession();




    }catch (Throwable t) {
        t.printStackTrace();
    }

i then retrieve each single Log istance in a for loop. staying in the loop i also add the object to the KieSession and fire the rule:

@Autowired
KieSessionFactory kieSessionFactory;



@Override
public void run() {

    KieSession kieS =  kieSessionFactory.getKieSessionCheckSavedLog();

    try {
        List<Log> logs = logRepo.getAllInGivenTimeSec(10);
        for(Log l : logs) {
            kieS.insert(l);
            kieS.fireAllRules();
        }
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

Here comes the rule i've written:

package com.sample 
import it.protodrools.beans.Log;

dialect "java"

rule "log2"
    when
        $l1 : Log( eventType == 2 && riskLevelId == 1);
        $l2 : Log( this != $l1 && eventType == 3 && riskLevelId == 1 );
    then
       System.out.println( "deadly threat !" );
end

My question is: will this rule take in account the whole list of objects that i'm passing ( though not via List, as i've read this is not a good practice ) and thus consider whether there's a condition-matching pair of object among those i'v passed ?

woukd you suggest some different workaround ?

thanks in advance

No, it will not.

for(Log l : logs) {
    kieS.insert(l);
    kieS.fireAllRules();
}

According to your loop you will insert an object and after each insert immediately afterwards you fire all rules. I am not sure how Drools will react to your loop, but what you probably want to do is insert all Logs in the working memory and then fire the rules:

for(Log l : logs) {
    kieS.insert(l);
}
kieS.fireAllRules();

Designing a JUnit test class would show you this immediately though.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM