Hello conrads.<div><br></div><div>To explain what I need, the problem that I found and the solution that I planning to use, I will firstly describe my cenario.</div><div><br></div><div><b><font size="6">Cenario</font></b></div>
<div>In my cenario, I have a declarative model and rules of different groups. I need put each rules group in a different knowledge base and all of it will share the same declarative model.</div><div><br></div><div>In a time, I will create a fact using fact types defined in a knowledge base that I will call as <font face="courier new, monospace">kbaseModel</font>. This knowledge base will have only the declarative model and no rules.</div>
<div><br></div><div>All facts created will be used in other knowledge base, called <font face="courier new, monospace">kbaseRules</font>. All <font face="courier new, monospace">kbaseRules</font> have only rules and no declarative model, because model was defined in <font face="courier new, monospace">kbaseModel</font>.</div>
<div><br></div><div>I could have many <font face="courier new, monospace">kbaseRules</font> but exists only one <font face="courier new, monospace">kbaseModel</font>.</div><div><br></div><div>Using the Drools API, teoricaly, I could implement my cenario using the following code:</div>
<div><br></div><div><font face="courier new, monospace">//DRL for resourceModel</font></div><div><div><font face="courier new, monospace">declare MyEntity</font></div><div><font face="courier new, monospace">   name : String</font></div>
<div><font face="courier new, monospace">end</font></div></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">//DRL for resourceRules</font></div><div><div><font face="courier new, monospace">rule &quot;Simple Rule&quot;</font></div>
<div><font face="courier new, monospace">   when</font></div><div><font face="courier new, monospace">      $entity: MyEntity()</font></div><div><font face="courier new, monospace">   then</font></div><div><font face="courier new, monospace">      System.out.println($entity)</font></div>
<div><font face="courier new, monospace">   end</font></div></div><div><br></div><div><font face="courier new, monospace">Resource resourceModel = ... //Resource with only the declarative model and no rules</font></div><div>
<font face="courier new, monospace">Resource resourceRules = ... //Resource with only rules and no declarative model</font></div><div><font face="courier new, monospace"><br></font></div><div><div><font face="courier new, monospace">KnowledgeBuilder kbuilderModel = KnowledgeBuilderFactory.newKnowledgeBuilder();</font></div>
<div><font face="courier new, monospace">kbuilderModel add(resourceModel, ResourceType.DRL);</font></div><div><font face="courier new, monospace">KnowledgeBase kbaseModel = kbuilderModel.newKnowledgeBase();</font></div></div>
<div><font face="courier new, monospace"><br></font></div><div><div><font face="courier new, monospace">KnowledgeBuilder kbuilderRules = KnowledgeBuilderFactory.newKnowledgeBuilder(kbaseModel);</font></div><div><font face="courier new, monospace">kbuilderRules.add(resourceRules, ResourceType.DRL);</font></div>
</div><div><div><font face="courier new, monospace">KnowledgeBase kbaseRules = KnowledgeBaseFactory.newKnowledgeBase();</font></div><div><font face="courier new, monospace">kbaseRules.addKnowledgePackages(kbuilderRules.getKnowledgePackages());</font></div>
</div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">FactType factType = kbaseModel.getFactType(&quot;mymodel&quot;, &quot;MyEntity&quot;);</font></div><div><div><font face="courier new, monospace">Object myEntity = factType.newInstance();</font></div>
<div><font face="courier new, monospace">factType.set(myEntity, &quot;name&quot;, &quot;Jackson Cunha Cassimiro&quot;);</font></div></div><div><font face="courier new, monospace"><br></font></div><div><div><font face="courier new, monospace">StatelessKnowledgeSession session = kbaseRules.newStatelessKnowledgeSession();</font></div>
<div><font face="courier new, monospace">session.execute(myEntity);</font></div></div><div><br></div><div>This code should work, but when I try to run I get this stacktrace:</div><div><span style="font-family:&#39;Courier New&#39;;font-size:12px"><br>
</span></div><div><span style="font-family:&#39;Courier New&#39;;font-size:12px">java.lang.ClassNotFoundException: Unable to load class: mymodel.MyEntity</span></div><div><span style="font-size:12px;font-family:&#39;Courier New&#39;;vertical-align:baseline">    at org.drools.util.CompositeClassLoader.loadClass(CompositeClassLoader.java:92)</span><br>
<span style="font-size:12px;font-family:&#39;Courier New&#39;;vertical-align:baseline">    at org.drools.common.AbstractRuleBase.registerAndLoadTypeDefinition(AbstractRuleBase.java:649)</span><br><span style="font-size:12px;font-family:&#39;Courier New&#39;;vertical-align:baseline">    at org.drools.common.AbstractRuleBase.addPackages(AbstractRuleBase.java:553)</span><br>
<span style="font-size:12px;font-family:&#39;Courier New&#39;;vertical-align:baseline">    at org.drools.reteoo.ReteooRuleBase.addPackages(ReteooRuleBase.java:472)</span><br><span style="font-size:12px;font-family:&#39;Courier New&#39;;vertical-align:baseline">    at org.drools.impl.KnowledgeBaseImpl.addKnowledgePackages(KnowledgeBaseImpl.java:150)</span><br>
<span style="font-size:12px;font-family:&#39;Courier New&#39;;vertical-align:baseline">    at app.UsingDeclares.main(UsingDeclares.java:79)</span><br><span style="font-size:12px;font-family:&#39;Courier New&#39;;vertical-align:baseline">Exception in thread &quot;main&quot; org.drools.RuntimeDroolsException: unable to resolve Type Declaration class &#39;mymodel.MyEntity&#39;</span><br>
<span style="font-size:12px;font-family:&#39;Courier New&#39;;vertical-align:baseline">    at org.drools.common.AbstractRuleBase.addPackages(AbstractRuleBase.java:582)</span><br><span style="font-size:12px;font-family:&#39;Courier New&#39;;vertical-align:baseline">    at org.drools.reteoo.ReteooRuleBase.addPackages(ReteooRuleBase.java:472)</span><br>
<span style="font-size:12px;font-family:&#39;Courier New&#39;;vertical-align:baseline">    at org.drools.impl.KnowledgeBaseImpl.addKnowledgePackages(KnowledgeBaseImpl.java:150)</span><br><span style="font-size:12px;font-family:&#39;Courier New&#39;;vertical-align:baseline">    at app.UsingDeclares.main(UsingDeclares.java:79)</span><br>
</div><div><br></div><div>It happens because Drools can&#39;t find any reference of <span style="font-family:&#39;Courier New&#39;;font-size:12px">mymodel.MyEntity </span><font face="arial, helvetica, sans-serif" style="font-size:12px">in </font><font face="courier new, monospace" style="font-size:12px">kbaseRules</font><font face="arial, helvetica, sans-serif" style="font-size:12px">, but this kbase was built from </font><font face="courier new, monospace" style="font-size:12px">kbaseModel</font><font face="arial, helvetica, sans-serif"><span style="font-size:12px"> that already have this class declared. </span><font size="4"><b style="background-color:rgb(255,255,0)">I think it can be a </b><b style="background-color:rgb(255,255,0)">bug</b></font><span style="font-size:12px">.</span></font></div>
<div><br></div><div><div><b><font size="6">Debuging</font></b></div><div>During creation of kbaseModel, a method called <font face="courier new, monospace">mergePackage(pkgRegistry, packageDescr)</font><span style="font-family:Arial"> from </span><font face="courier new, monospace">PackageBuilder</font><span style="font-family:Arial"> class is invoked. The </span><font face="courier new, monospace">pkgRegistry</font><span style="font-family:Arial"> not contains any reference to declarative model. The </span><font face="courier new, monospace">packageDescr</font><span style="font-family:Arial"> contains a list of type definitions from declarative model. Inside </span><font face="courier new, monospace">mergePackage</font><span style="font-family:Arial"> is invoked other method, called </span><font face="courier new, monospace">processTypeDeclarations(pkgRegistry, packageDescr)</font><span style="font-family:Arial"> that will iterate over all type definitions from </span><font face="courier new, monospace">packageDescr</font><font face="arial, helvetica, sans-serif"> and will fill a map called </font><font face="courier new, monospace">Map&lt;String,byte[]&gt; classLookups</font><font face="arial, helvetica, sans-serif"> from </font><font face="courier new, monospace">JavaDialectRuntimeData</font><font face="arial, helvetica, sans-serif"> class.</font></div>
<div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif">During the creation of kbaseRules the method </font><font face="courier new, monospace">mergePackage(pkgRegistry, packageDescr)</font><span style="font-family:Arial"> from </span><font face="courier new, monospace">PackageBuilder</font><span style="font-family:Arial"> is invoked again, but at this time </span><font face="courier new, monospace">pkgRegistry</font><span style="font-family:Arial"> contains all type definitions defined previously in </span><font face="courier new, monospace">kbaseModel</font><span style="font-family:Arial"> and </span><font face="courier new, monospace">packageDescr</font><span style="font-family:Arial"> not contains any type definitions, only rules. When the method</span><font face="courier new, monospace"> processTypeDeclarations(pkgRegistry, packageDescr)</font><span style="font-family:Arial"> from </span><font face="courier new, monospace">PackageBuilder</font><span style="font-family:Arial"> is called and try iterate over type definitions of </span><font face="courier new, monospace">packageDescr</font><span style="font-family:Arial">, this is empty and nothing is done and the map </span><font face="courier new, monospace">Map&lt;String,byte[]&gt; classLookups</font><span style="font-family:Arial"> from </span><font face="courier new, monospace">JavaDialectRuntimeData</font><span style="font-family:Arial"> will be empty too</span><span style="font-family:Arial;font-size:15px">.</span></div>
<div><span style="font-family:Arial;font-size:15px"><br></span></div><div><b><font size="4" style="background-color:rgb(255,255,102)"><span style="font-family:Arial">The </span><font face="courier new, monospace">classLookups</font><span style="font-family:Arial"> empty</span><span style="font-family:Arial"> is the cause of </span><font face="courier new, monospace">ClassNotFoundException</font></font></b><span style="font-family:&#39;Courier New&#39;;font-size:12px">.</span></div>
<div><span style="font-family:&#39;Courier New&#39;;font-size:12px"><br></span></div><div><font face="arial, helvetica, sans-serif" size="6"><b>Solution</b></font></div><div>The solution that I found was apply reflection to fill <font face="courier new, monospace">Map&lt;String,byte[]&gt; classLookups</font><span style="font-family:Arial"> from </span><font face="courier new, monospace">JavaDialectRuntimeData </font><span style="font-family:Arial">correctly before add the packages into </span><font face="courier new, monospace">kbaseRules</font><span style="font-family:Arial">: </span></div>
<div><span style="font-family:Arial"><br></span></div><div><div><font face="courier new, monospace">Collection&lt;KnowledgePackage&gt; packages = kbuilderRules.getKnowledgePackages();</font></div><div><font face="courier new, monospace">Mirror mirror = new Mirror();//Reflection utilities</font></div>
<div><span class="Apple-tab-span" style="white-space:pre"><font face="courier new, monospace">                </font></span></div><div><font face="courier new, monospace">for (KnowledgePackage kPackage : packages) {</font></div><div><font face="courier new, monospace">   Package pkg =  (Package) mirror.on(kPackage).get().field(&quot;pkg&quot;);</font></div>
<div><font face="courier new, monospace">   JavaDialectRuntimeData dialect = (JavaDialectRuntimeData) pkg.getDialectRuntimeRegistry().getDialectData( &quot;java&quot; );</font></div><div><span class="Apple-tab-span" style="white-space:pre"><font face="courier new, monospace">                        </font></span></div>
<div><font face="courier new, monospace">   for (FactType factType : kPackage.getFactTypes()) {</font></div><div><font face="courier new, monospace">      Class&lt;?&gt; c = factType.getFactClass();</font></div><div><font face="courier new, monospace">      String className = c.getName();</font></div>
<div><font face="courier new, monospace">      String classAsPath = className.replace(&#39;.&#39;, &#39;/&#39;) + &quot;.class&quot;;</font></div><div><font face="courier new, monospace">      InputStream stream = c.getClassLoader().getResourceAsStream(classAsPath);</font></div>
<div><font face="courier new, monospace">      byte[] bytes = IOUtils.toByteArray(stream);</font></div><div><font face="courier new, monospace">      dialect.putClassDefinition(classAsPath, bytes);</font></div><div><font face="courier new, monospace">   }</font></div>
<div><font face="courier new, monospace">}</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">KnowledgeBase kbaseRules = KnowledgeBaseFactory.newKnowledgeBase();</font></div>
<div><font face="courier new, monospace">kbaseRules.addKnowledgePackages(packages);</font></div></div><div><font face="arial, helvetica, sans-serif"><br></font></div><br>----------------------------------------------------------------------------------------------------------------<br>
Jackson Cunha Cassimiro (CereB)<br>Bacharel em Ciencia da Computação - UFPI<br>MSN: <a href="mailto:jackson.cereb@gmail.com" target="_blank">jackson.cereb@gmail.com</a><br>Telefone Móvel +55 86 9928 1251<br>Analista de Sistemas - Infoway - <a href="http://www.infoway-pi.com.br" target="_blank">http://www.infoway-pi.com.br</a><br>
Missão Infoway - &quot;Influenciar a Gestão de Sistemas de Saúde através de e-health&quot;<br><br>(&quot;A vida é um combate que os fracos abate, aos bravos, aos fortes só pode exaltar&quot; - Canção do Tamoio, Gonçalves Dias)<br>
----------------------------------------------------------------------------------------------------------------<br>
</div>