Hello,
I've been trying to compile the latest version of drools to .NET for a
few days now. However, due to the classloaders structure, the classes
in the org.drools.base.extractors.* are not found by the classloader,
and the execution stops with a NoClassDefFoundError for classes in
that package.
Here's some details about the setup:
Drools version: 5.0.1
IKVM Version: 0.40.0.1
I have successfully compiled all the required libraries into a DLL
using IKVM, and a simple rule (containing a null LHS) runs
successfully, all the classes are found, and the rule engine produces
the correct output. However, when I add a condition into the LHS, it
fails because it can't find one of the classes in
/org.drools.base.extractors..*Reader/
A sample rule I am using is:
"""
package package
import rules.Customer
import rules.VoucherSeries
rule "everything free for Krishna"
when
$c : Customer( firstname == "Krishna" )
then
VoucherSeries fact0 = new VoucherSeries();
fact0.setSeriesCode( "FREE" );
insert(fact0 );
end
"""
I have verified that all the classes are present in the classloader I
am passing to the KnowledgeBuilderConfiguration. In fact, I also tried
creating a MapBasedClassLoader that contains all the missing classes
so that they can be easily found using fastFindClass. In the code
listing below, both klass and klass2 resolve to the correct class
objects.
"""
java.util.Properties p = new java.util.Properties();
p.put("drools.dialect.java.compiler", "JANINO");
java.lang.ClassLoader cl =
java.lang.Class.forName("org.drools.base.extractors.BaseLongClassFieldReader").getClassLoader();
org.drools.rule.CompositeClassLoader compositeClassLoader
= new org.drools.rule.CompositeClassLoader(cl);
org.drools.rule.MapBackedClassLoader mbcl =
getMapBackedClassLoader(cl);
compositeClassLoader.addClassLoader(mbcl);
java.lang.Class klass =
compositeClassLoader.fastFindClass("rules.Customer");
java.lang.Class klass2 =
compositeClassLoader.fastFindClass("org.drools.base.extractors.BaseObjectClassFieldReader");
java.lang.ClassLoader finalClassLoader = compositeClassLoader;
org.drools.builder.KnowledgeBuilderConfiguration kbc =
org.drools.builder.KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration(p,
finalClassLoader);
"""
However, adding the DRL / PKG file, it fails with the exception:
java.lang.NoClassDefFoundError was caught
Message="org.drools.base.extractors.BaseObjectClassFieldReader"
Source="IKVM.Runtime"
StackTrace:
at IKVM.NativeCode.java.lang.ClassLoader.defineClass1(Object
thisClassLoader, String name, Byte[] b, Int32 off, Int32 len, Object
pd, String source)
at java.lang.ClassLoader.defineClass1(String , Byte[] , Int32 ,
Int32 , ProtectionDomain , String )
at java.lang.ClassLoader.defineClass(String name, Byte[] b,
Int32 off, Int32 len, ProtectionDomain protectionDomain)
at org.drools.base.ClassFieldAccessorCache.ByteArrayClassLoader.defineClass(String
name, Byte[] bytes, ProtectionDomain domain)
at org.drools.base.ClassFieldAccessorFactory.getClassFieldReader(Class
clazz, String fieldName, CacheEntry cache)
at org.drools.base.ClassFieldAccessorCache.CacheEntry.getReadAccessor(AccessorKey
key, Class cls)
at org.drools.base.ClassFieldAccessorCache.getReadAcessor(ClassFieldReader
reader)
at org.drools.base.ClassFieldAccessorStore.wire(ClassFieldReader reader)
at org.drools.base.ClassFieldAccessorStore.getReader(String
className, String fieldName, AcceptsReadAccessor target, AccessorType
accessorType)
at org.drools.base.ClassFieldAccessorStore.getReader(String
className, String fieldName, AcceptsReadAccessor target)
at org.drools.rule.builder.PatternBuilder.getFieldReadAccessor(RuleBuildContext
context, BaseDescr descr, ObjectType objectType, String fieldName,
AcceptsReadAccessor target, Boolean reportError)
at org.drools.rule.builder.PatternBuilder.build(RuleBuildContext
, Pattern , FieldConstraintDescr , AbstractCompositeConstraint )
at org.drools.rule.builder.PatternBuilder.buildConstraint(RuleBuildContext
, Pattern , Object , AbstractCompositeConstraint )
at org.drools.rule.builder.PatternBuilder.build(RuleBuildContext
context, BaseDescr descr, Pattern prefixPattern)
at org.drools.rule.builder.PatternBuilder.build(RuleBuildContext
context, BaseDescr descr)
at org.drools.rule.builder.GroupElementBuilder.build(RuleBuildContext
context, BaseDescr descr, Pattern prefixPattern)
at org.drools.rule.builder.RuleBuilder.build(RuleBuildContext context)
at org.drools.compiler.PackageBuilder.addRule(RuleDescr )
at org.drools.compiler.PackageBuilder.addPackage(PackageDescr
packageDescr)
at org.drools.compiler.PackageBuilder.addPackageFromDrl(Resource
resource)
at org.drools.compiler.PackageBuilder.addKnowledgeResource(Resource
resource, ResourceType type, ResourceConfiguration configuration)
at org.drools.builder.impl.KnowledgeBuilderImpl.add(Resource
resource, ResourceType type)
at Capillary.Client.RulesEngine.RuleManager.ReadRules(String
filename) in
D:\coderoot\module\DataEntryClient-DVS\SubProjects\RulesEngine\RuleManager.cs:line
116
InnerException:
I saw the code at org/drools/base/ClassFieldAccessorCache.java, and it
seems me that the Reader class for the particular type is being
defined in situ using a byte[] array, but I am unable to understand
why it can't load the class at that point.
Can anybody with a better idea of the drools classloading structure
guide me here?
Also, is the
drools.NET project active now? I would post all the steps
I took for posterity.
Thanks and Regards,
Krishna.
--
http://kpowerinfinity.wordpress.com
http://www.linkedin.com/in/kpowerinfinity