[rules-dev] Compiling drools-5 to .NET -- issue with ClassLoaders

kpowerinfinity kpowerinfinity at gmail.com
Fri Sep 4 22:57:21 EDT 2009


Hi Michael,

It seems that the CacheFieldAccessorCache is not initialized with the
same ClassLoader as the one one provided to the
KnowledgeBaseConfiguration, if initialized by default, but rather does
it using
Class.forName("some.model.class").getClassLoader()

Hence, the ClassLoader was unable to resolve the drools base extractor classes.

IKVM had moved to a new classloading architecture , and the default
classloader that gets attached doesn't resolve the other classes.
(See: http://weblog.ikvm.net/CommentView.aspx?guid=8a457a80-1e5f-4182-8f78-b2cd67845553),
and by making the model class as a AppDomainAssemblyClassLoader), it
is able to resolve all loaded classes and it works perfectly.

Thought I'd post the resolution here.

Regards
Krishna.

--
http://kpowerinfinity.wordpress.com
http://www.linkedin.com/in/kpowerinfinity




On Fri, Sep 4, 2009 at 8:03 AM, Michael Neale<michael.neale at gmail.com> wrote:
> would have to look at the code for that - its the only documentation
> that makes sense for something so low-level...
>
> I don't think there were major changes in Drools 4 to 5 in that area -
> so odd that it doesn't work.
>
> On Fri, Sep 4, 2009 at 1:01 AM, kpowerinfinity<kpowerinfinity at gmail.com> wrote:
>> Hi Mike,
>>
>> Do you remember what you needed to do for drools3.0? I had earlier
>> compiled drools 4.0 and it seemed to work without any major problems.
>>
>> Where can I find some documentation on the ASM and where drools picks
>> up the classes from while generating the "in-situ" classes?
>>
>> Thanks, Krishna.
>>
>> --
>> http://kpowerinfinity.wordpress.com
>> http://www.linkedin.com/in/kpowerinfinity
>>
>>
>>
>>
>> On Thu, Sep 3, 2009 at 5:31 AM, Michael Neale<michael.neale at gmail.com> wrote:
>>> Hi Krishna - I don't think the .Net version on the codehaus is kept
>>> that up to date, so its probably a good thing you are doing what you
>>> are doing with the latest.
>>>
>>> Yes, those accessor classes are indeed lazily generated and loaded
>>> "in-situ" - this is for fast access of fields in the alpha network
>>> which can be hit hard and often... an inlined version of the ASM
>>> library is used to do this.
>>>
>>> I am pretty sure that even in drools 3 we did something like this
>>> (also using ASM) and that was able to work with IKVM - so there must
>>> be some small change that has made the IKVM classloader angry...
>>>
>>> On a barely related note: is it worth thinking about a Source to
>>> Source translator to C# - there are a few around (ILog even open
>>> sourced one, although it didn't cope with Generics last I checked...)
>>> ?
>>>
>>>
>>> Michael.
>>>
>>> On Wed, Sep 2, 2009 at 11:56 PM, kpowerinfinity<kpowerinfinity at gmail.com> wrote:
>>>> 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
>>>> _______________________________________________
>>>> rules-dev mailing list
>>>> rules-dev at lists.jboss.org
>>>> https://lists.jboss.org/mailman/listinfo/rules-dev
>>>>
>>>
>>>
>>>
>>> --
>>> Michael D Neale
>>> home: www.michaelneale.net
>>> blog: michaelneale.blogspot.com
>>>
>>> _______________________________________________
>>> rules-dev mailing list
>>> rules-dev at lists.jboss.org
>>> https://lists.jboss.org/mailman/listinfo/rules-dev
>>>
>>
>> _______________________________________________
>> rules-dev mailing list
>> rules-dev at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/rules-dev
>>
>
>
>
> --
> Michael D Neale
> home: www.michaelneale.net
> blog: michaelneale.blogspot.com
>
> _______________________________________________
> rules-dev mailing list
> rules-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/rules-dev
>



More information about the rules-dev mailing list