In the mean time I've done a series of examples, which demonstrates both the convention and the api approach - both on their own and used in conjunction:
https://github.com/droolsjbpm/drools/tree/master/drools-examples-api
The simplest example needs an empty kmodule.xml file:
https://github.com/droolsjbpm/drools/blob/master/drools-examples-api/default-kiesession/src/main/resources/META-INF/kmodule.xml
then session can be created from just two lines:
https://github.com/droolsjbpm/drools/blob/master/drools-examples-api/default-kiesession/src/main/java/org/drools/example/api/defaultkiesession/DefaultKieSessionExample.java
The kmodule.xml is necessary for discovery, from that we can find all the drl, bpmn2 files for the kiebase - without the user having to specify each file individually.
However we now support kiemodules. These are named kiebases that are available for lookup, and deployed via maven. Further one kiemodule can now "include" resources from other kiemodules - s owe have better composition.
This works really well for CDI, where can now remove all boiler plate code and simply use annotations to inject sessions:
https://github.com/droolsjbpm/drools/blob/master/drools-examples-cdi/cdi-example-with-inclusion/src/main/java/org/drools/example/cdi/cdiexamplewithinclusion/CDIExampleWithInclusion.java
Mark
On 25 Mar 2013, at 15:56, Geoffrey De Smet <ge0ffrey.spam@gmail.com> wrote:
I've upgraded OptaPlanner to use the KIE api and I have some
feedback :)
What I want to do:
Given of list of DRL's on the classpath, build a KieSession.
Here's how I did it with the new KIE api:
public KieBase newKieBase(List<String> scoreDrlList) {
KieServices kieServices =
KieServices.Factory.get();
KieResources kieResources
= kieServices.getResources();
KieFileSystem
kieFileSystem = kieServices.newKieFileSystem();
for (String scoreDrl : scoreDrlList) {
InputStream scoreDrlIn =
getClass().getResourceAsStream(scoreDrl);
// TODO newClassPathResource() instead, but that
breaks (mfusco is looking at it)
String path =
"src/main/resources/optaplanner-kie-namespace/" + scoreDrl;
kieFileSystem.write(path,
kieResources.newInputStreamResource(scoreDrlIn, "UTF-8"));
}
KieBuilder kieBuilder =
kieServices.newKieBuilder(kieFileSystem);
kieBuilder.buildAll();
Results results =
kieBuilder.getResults();
if (results.hasMessages(Message.Level.ERROR)) {
throw new IllegalStateException("There are errors in
the scoreDrl's:\n"
+ results.toString());
} else if (results.hasMessages(Message.Level.WARNING)) {
logger.warn("There are warning in the scoreDrl's:\n"
+ results.toString());
}
KieContainer kieContainer
= kieServices.newKieContainer(kieBuilder.getKieModule().getReleaseId());
KieBase kieBase =
kieContainer.getKieBase();
return kieBase;
}
public KieSession newKieSession() {
...
KieSession kieSession = kieBase.newKieSession();
return kieSession;
}
Feedback (note: these are suggestions, not demands):
1) To do this, I needed to get acquainted with 9 new concepts:
KieServices, KieResources, KieFileSystem, KieBuilder, Results,
KieModule, KieContainer, KieBase, KieSession.
I only care about 2 of those:
- KieSession
- KieBase (= the factory to build a new KieSession, which I do
regularly).
The other 7 concepts probably represent wonderful advanced features
which I might want to use later on,
so they should exist,
But in a simple use case like this, I should not have to see them or
deal with them.
2) The kie filesystem features leaks into the simple api, even if I
don't care about the KieFileSystem at all.
- I should not explicitly need to create a KieFileSystem:
KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
- Adding certain Resource types fails if you don't specify the
fileSystem's path. This fails for example:
kieFileSystem.write(kieResources.newInputStreamResource(...));
- For the default KieBase to work, the path needs to start with a magical prefix
String path = "src/main/resources/.../"
+ ...;
3) To create a KieBase from that kieFileSystem, I need to explicitly
do 5+ calls, in the right order:
- call kieServices.newKieBuilder(...)
- call kieBuilder.buildAll()
- call kieBuilder.getKieModule()
- call kieServices.newKieContainer(...)
- call kieContainer.getKieBase()
Some of these have non-obvious parameters.
I'd rather just call:
kieFileSystem.buildKieBase()
4) I don't like having to write the boilerplate code to check if the
are errors:
if (results.hasMessages(Message.Level.ERROR)) {...}
If there are errors, then kieFileSystem.buildKieBase() should just
throw a DroolsRuntimeException.
Solution proposal:
A) Write a facade class that presumes there is only 1 module and the
user doesn't need (or want to) to access any of those 7 other
concepts.
public KieBase newKieBase(List<String> scoreDrlList) {
KieBaseFactory kieBaseFactory =
kieServices.newKieBaseFactory();
for (String scoreDrl : scoreDrlList) {
kieBaseFactory.addInputStreamResource(scoreDrl, "UTF-8");
}
return kieBaseFactory.buildKieBase; // throws exception upon
compilation error
}
Mario's KieHelper is similar, but slightly different.
wkr,
Geoffrey
_______________________________________________
rules-dev mailing list
rules-dev@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-dev