Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loading and updating rules from a database in Drools 6

Tags:

java

drools

How would one go about loading rules from a database table at startup and updating them from the same table in Drools 6.2.0? I've found an example using Drools 5 that I could probably convert from Scala to Java but it looks like the API has changed pretty drastically... I don't see the RuleBaseFactory class, for example.

Any sample or documentation would be appreciated.

like image 907
user506069 Avatar asked May 14 '15 17:05

user506069


2 Answers

I'm not sure from where that org.drools.RuleBaseFactory was taken. Below is how it was done in Drools 5.3 (and possibly earlier) up to 5.6:

KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add( ..., ResourceType.DRL);
if( kbuilder.hasErrors() ){
    System.err.println( "### compilation errors ###" );
    KnowledgeBuilderErrors errors = kbuilder.getErrors();
    for( KnowledgeBuilderError err: errors ){
        System.err.println( err.toString() );
    }
    throw new IllegalStateException( "compile errors" );
}
KnowledgeBase kbase = kbuilder.newKnowledgeBase();
StatelessKnowledgeSession ksession = kbase.newStatelessKnowledgeSession();

The ellipsis indicates the place for inserting the data holding the rule text. Check the API for suitable types; a java.lang.String should be acceptable.

This is the way I use for 6.2:

KieServices kieServices = KieServices.Factory.get();
KieFileSystem kfs = kieServices.newKieFileSystem();
kfs.write( "src/main/resources/simple.drl", ... );
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();
like image 114
laune Avatar answered Sep 20 '22 14:09

laune


drools-templates has ResultSetGenerator.java which has method compile(resultSet, template) to do the job.

I had data coming over HTTP to be converted to rule. I found a way to do this using ObjectDataCompiler. May be some people might find this useful.

ObjectDataCompiler compiler = new ObjectDataCompiler();
String generatedDRL = compiler.compile(ruleAttributes, new FileInputStream(REGULATION_TEMPLATE_FILE));

where ruleAttributes is

List<Map<String, String>> ruleAttributes = new ArrayList<>();
Map<String, String> rule1 = new HashMap<>();
rule1.put("ruleid", "2");
rule1.put("ifcondition", "abc: Abc(xyz.getId() == 2);");
rule1.put("thencondition", "myGlobal.setPqr(200.1D);");
ruleAttributes.add(rule1);

KieBase can then be created like this:

KieServices kieServices = KieServices.Factory.get();

KieHelper kieHelper = new KieHelper();

//multiple such resoures/rules can be added
byte[] b1 = generatedDRL.getBytes();
Resource resource1 = kieServices.getResources().newByteArrayResource(b1);
kieHelper.addResource(resource1, ResourceType.DRL);

KieBase kieBase = kieHelper.build();

Rules can be applied like this:

KieSession kieSession = kieBase.newKieSession();
kieSession.setGlobal("myGlobal", myGlobal);
kieSession.insert(abc);
int numberOfRulesFired = kieSession.fireAllRules();
kieSession.dispose();

Template file looks like this:

template header
ruleid
ifcondition
thencondition

import fk.sp.seldon.msku.MSKU

global com.something.blah.MyGlobal myGlobal

template "tmp1"

rule "@{ruleid}"
  dialect "mvel"
  when
    @{ifcondition}
  then
    @{thencondition};
end
end template
like image 39
Rajvidya Chandele Avatar answered Sep 22 '22 14:09

Rajvidya Chandele