Reputation: 1180
I am new to drools. I am facing a problem with drools engine. I have a user who can create rules from the web interface and I using some code will create the drl file out of those rules. Till here everything is working as expected. Now the user will provide inputs through a post request to the exposed api and based on some parameter value we will pick a single drl file and execute the rules. Earlier what I was doing, for every request I was reading the drl file which I have generated into kieFileSystem and building it. So if a user sends 3 parameter then I was building 3 different files one by one and executed them which was slow.(It was taking around 1 sec for 3 parameters, and parameters have no restriction so he can also send 10-12 which will be pretty slow.)
public <T> void getScore(T droolsInput, String filePath, String fileName) throws Exception {
KieServices kieServices = KieServices.Factory.get();
KieFileSystem kfs = kieServices.newKieFileSystem();
FileInputStream fis = new FileInputStream(filePath);
kfs.write(fileName, kieServices.getResources().newInputStreamResource(fis));
KieBuilder kieBuilder = kieServices.newKieBuilder(kfs).buildAll();
if (kieBuilder.getResults().hasMessages(Level.ERROR)) {
throw new RuntimeException("Build Errors:\n" + kieBuilder.getResults().toString());
}
KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());
KieSession kieSession = kieContainer.newKieSession();
kieSession.insert(droolsInput);
kieSession.fireAllRules();
kieSession.dispose();
fis.close();
}
this is the code i was using earlier. Now i came to know about kmodule.xml, how i can build kbases and ksession on starting up my application and my response time went from 1 sec to almost 300msec. But the problem is i need to create kmodule.xml file before starting up my application in META-INF folder otherwise it isn't working.(I dont know whether i am doing some thing wrong or what). So when the user updates the rules using the web interface we again build the drl file and when he hits api we give want to give him output according to new rules. We dont want to restart the application to reploy the rules. Their can be many users using the service. So can anyone help me with this. Basically what i want is to keep the rules updated and also keep the response time as low as possible.
This is the code i used to generate kmodule.xml which is not working for me.
private Resource[] getRuleFiles() throws IOException {
ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
return resourcePatternResolver.getResources("classpath*:" + RULES_PATH + "**/*.*");
}
@Bean
public KieContainer buildKIEContainer() throws IOException {
final KieRepository kieRepository = getKieServices().getRepository();
kieRepository.addKieModule(new KieModule() {
@Override
public ReleaseId getReleaseId() {
return kieRepository.getDefaultReleaseId();
}
});
System.out.println("#############################################################################");
System.out.println(getRuleFiles()[0].getURL());
// System.out.println();
KieModuleModel kieModuleModel = getKieServices().newKieModuleModel();
// KieFileSystem kieFileSystem = kieFileSystem();
for (Resource file : getRuleFiles()) {
String fileNameWithoutExt = file.getFilename().split("\\.")[0];
KieBaseModel kieBaseModel1 = kieModuleModel.newKieBaseModel(fileNameWithoutExt).setDefault(true)
.setEqualsBehavior(EqualityBehaviorOption.EQUALITY)
.setEventProcessingMode(EventProcessingOption.STREAM);
kieBaseModel1.newKieSessionModel("session_" + fileNameWithoutExt).setDefault(true)
.setType(KieSessionModel.KieSessionType.STATEFUL).setClockType(ClockTypeOption.get("realtime"));
kieBaseModel1.addPackage("rules." + fileNameWithoutExt);
FileInputStream fis = new FileInputStream(file.getFile());
kieFileSystem.write("src/main/resources/rules/" + fileNameWithoutExt + "/" + file.getFilename(),
getKieServices().getResources().newInputStreamResource(fis));
}
System.out.println(kieModuleModel.toXML());
kieFileSystem.writeKModuleXML(kieModuleModel.toXML());
KieBuilder kieBuilder = getKieServices().newKieBuilder(kieFileSystem);
kieBuilder.buildAll();
if (kieBuilder.getResults().hasMessages(Level.ERROR)) {
throw new RuntimeException("Build Errors:\n" + kieBuilder.getResults().toString());
}
return getKieServices().newKieClasspathContainer("mycontainer");
}
public KieServices getKieServices() {
return KieServices.Factory.get();
}
@Bean
public KieFileSystem kieFileSystem() throws IOException {
return getKieServices().newKieFileSystem();
}
And this is the code i am using to fire the rules.
@Autowired
private KieContainer kieContainer;
public <T> void getScore(T droolsInput, String filePath, String fileNameWithPath, String filename)
throws Exception {
KieSession kieSession = kieContainer.newKieSession("session_" + filename.split("\\.")[0]);
kieSession.insert(droolsInput);
kieSession.fireAllRules();
kieSession.dispose();
}
So basically the above fireRules code work if the kmodule.xml is present in META-INF folder in project otherwise it doesn't works.
Upvotes: 3
Views: 1329
Reputation: 31300
It should be possible to compile each DRL file individually to obtain a KiePackage, and to combine them arbitrarily (according to the parameters) into a KieBase from which the session is generated. But I think that requires access to the internals API which is subject to change without further notice.
Therefore I would use another approach.
Add a
class Parameters {
Set<String> set = ...
}
and one rule for each X.drl:
rule selectX
when
Parameters( set contains "X" ) # pattern to select X
then
end
and write all rules in X.drl
rule some_rule_in_X
extends selectX
// ...
Alternatively, write the pattern to select X into every rule.
To activate, insert an object of class Parameters derived from the post request.
Upvotes: 1