<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    I've upgraded OptaPlanner to use the KIE api and I have some
    feedback :)<br>
    <br>
    What I want to do:<br>
    <b>Given of list of DRL's on the classpath, build a KieSession.</b><br>
    <br>
    Here's how I did it with the new KIE api:<br>
    <br>
         public KieBase newKieBase(List&lt;String&gt; scoreDrlList) {<br>
                <font color="#cc6600">KieServices</font> kieServices =
    KieServices.Factory.get();<br>
                <font color="#cc6600">KieResources</font> kieResources
    = kieServices.getResources();<br>
                <font color="#cc6600">KieFileSystem</font>
    kieFileSystem = kieServices.newKieFileSystem();<br>
                for (String scoreDrl : scoreDrlList) {<br>
                    InputStream scoreDrlIn =
    getClass().getResourceAsStream(scoreDrl);<br>
                    // TODO newClassPathResource() instead, but that
    breaks (mfusco is looking at it)<br>
                    String path =
    "src/main/resources/optaplanner-kie-namespace/" + scoreDrl;<br>
                    kieFileSystem.write(path,
    kieResources.newInputStreamResource(scoreDrlIn, "UTF-8"));<br>
                }<br>
                <font color="#cc6600">KieBuilder</font> kieBuilder =
    kieServices.newKieBuilder(kieFileSystem);<br>
                kieBuilder.buildAll();<br>
                <font color="#cc6600">Results</font> results =
    kieBuilder.getResults();<br>
                if (results.hasMessages(Message.Level.ERROR)) {<br>
                    throw new IllegalStateException("There are errors in
    the scoreDrl's:\n"<br>
                            + results.toString());<br>
                } else if (results.hasMessages(Message.Level.WARNING)) {<br>
                    logger.warn("There are warning in the scoreDrl's:\n"<br>
                            + results.toString());<br>
                }<br>
                <font color="#cc6600">KieContainer</font> kieContainer
    = kieServices.newKieContainer(kieBuilder.get<font color="#cc6600">KieModule</font>().getReleaseId());<br>
                <font color="#cc6600">KieBase</font> kieBase =
    kieContainer.getKieBase();<br>
                return kieBase;<br>
         }<br>
    <br>
         public KieSession newKieSession() {<br>
                ...<br>
                KieSession kieSession = kieBase.newKieSession();<br>
                return kieSession;<br>
         }<br>
    <br>
    <b>Feedback</b> (note: these are suggestions, not demands):<br>
    <br>
    1) To do this, I needed to get acquainted with <font
      color="#cc6600">9 new concepts</font>:<br>
        KieServices, KieResources, KieFileSystem, KieBuilder, Results,
    KieModule, KieContainer, KieBase, KieSession.<br>
    I only care about 2 of those:<br>
    - KieSession<br>
    - KieBase (= the factory to build a new KieSession, which I do
    regularly).<br>
    The other 7 concepts probably represent wonderful advanced features
    which I might want to use later on,<br>
    so they should exist,<br>
    But in a simple use case like this, I should not have to see them or
    deal with them.<br>
    <br>
    2) The kie filesystem features leaks into the simple api, even if I
    don't care about the KieFileSystem at all.<br>
    - I should not explicitly need to create a KieFileSystem:<br>
        KieFileSystem kieFileSystem = kieServices.newKieFileSystem();<br>
    - Adding certain Resource types fails if you don't specify the
    fileSystem's path. This fails for example:<br>
        kieFileSystem.write(kieResources.newInputStreamResource(...));<br>
    - For the default KieBase to work, the path needs to start with a <font
      color="#993399">magical</font> prefix<br>
        String path = "<font color="#993399">src/main/resources</font>/.../"
    + ...;<br>
    <br>
    3) To create a KieBase from that kieFileSystem, I need to explicitly
    do 5+ calls, in the right order:<br>
    - call kieServices.newKieBuilder(...)<br>
    - call kieBuilder.buildAll()<br>
    - call kieBuilder.getKieModule()<br>
    - call kieServices.newKieContainer(...)<br>
    - call kieContainer.getKieBase()<br>
    Some of these have non-obvious parameters.<br>
    I'd rather just call:<br>
      kieFileSystem.buildKieBase()<br>
    <br>
    4) I don't like having to write the boilerplate code to check if the
    are errors:<br>
      if (results.hasMessages(Message.Level.ERROR)) {...}<br>
    If there are errors, then kieFileSystem.buildKieBase() should just
    throw a DroolsRuntimeException.<br>
    <br>
    <b>Solution</b> proposal:<br>
    <br>
    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.<br>
    <br>
        public KieBase newKieBase(List&lt;String&gt; scoreDrlList) {<br>
            KieBaseFactory kieBaseFactory =
    kieServices.newKieBaseFactory();<br>
            for (String scoreDrl : scoreDrlList) {<br>
               kieBaseFactory.addInputStreamResource(scoreDrl, "UTF-8");<br>
            }<br>
            return kieBaseFactory.buildKieBase; // throws exception upon
    compilation error<br>
        }<br>
    <br>
    Mario's KieHelper is similar, but slightly different.<br>
    <br>
    wkr,<br>
    Geoffrey<br>
    <br>
  </body>
</html>