[rules-users] IllegalAccessError in shadow classes
Mark Proctor
mproctor at codehaus.org
Thu Feb 21 00:33:30 EST 2008
Godmar Back wrote:
> On Wed, Feb 20, 2008 at 9:40 PM, Mark Proctor <mproctor at codehaus.org> wrote:
>
>> Btw when you use MVEL notation to access nested objects, like you do with a
>> Map, we just re-write it as an eval. This means you won't get any of the
>> indexing performance. You can still get indexing if you represent your facts
>> with FactTemplates.
>>
>>
>
> FWIW - I used MVEL notation to bypass the restriction that function
> calls aren't allowed on LHS, not for indexing reasons, that is,
> e["prop"] instead of e.get("prop") which to Drools looks like a
> function call with a potential side effects. I had hoped to avoid
> turning my maps into POJOs/beans; additionally, one of my goals is to
> keep my rule base easily readable (thus avoid the explicit use of
> eval()).
>
Yes thats why we allow the MVEL notation, to help keep the readability
of propositional logic, without having to resort to encapsulating with
an eval, which adds verbosity. But its good to remember that internally
we just re-write this as an eval anyway.
> Regarding your other comment about supporting Maps are special fact
> types - you mention that you'd lose type information - that's not
> necessarily the case if you postulate that only maps whose key set and
> value types don't change past insertion. In that case, you can find
> the type via runtime reflection on the concrete objects being carried
> in the map.
That would provide you the type fields, but not the type of the fact
itself. i.e. you are making all your facts of the same type, so you
loose the top level of descrimination. Only work around for that is if
you designate one of the fields to declare the fact objecttype for that
map. But this is getting yucky.
> Overall, though, I agree that it's probably only a
> stopgap measure and a better design is required. See also my other
> comment about what uses Drools should provide for IMO.
>
Your welcome to play around with FactTemplates now, I know other users
have done so. What do you think about runtime bean generation, if the
engine can take care of this for you, you just define the object structure?
> - Godmar
>
>
>> Mark
>> Mark Proctor wrote:
>>
>> Personally I don't like the idea of a Map as a model as it has no type, so
>> straight away you lose object level descrimination. Also a Map is not
>> declarative in defining what it is you are reasoning over. It's a hack to
>> get over the limitations of the current environment.
>>
>> In the engine we have something called FactTemplats, which we do not
>> currently document - it's a hidden feature. These work much less Jess
>> Deftemplates, and where infact made so that we could support a Jess/clips.
>> The implementation is basically an array and uses name tokenising to get
>> access. i.e. you write person.name == "Godmar" and we rewrite it as
>> person.setField( 0, "Godmar" ). Although we haven't yet got the rewritting
>> part done so currently you have to manually do the above, or make it lookup
>> the position each time with person.setField( "name", "Godmar" ). These
>> FactTemplates can be reasoned over in the LHS just like pojos.
>>
>> However I'm not currently happy with the solution and thinking instead of
>> going down the route of runtime bean generation. This would allow you to
>> define models at runtime, without caring about the underlying
>> implementation, and still give us pojos to work with and also provides more
>> performance. further to this we really want to do our model implementation
>> with ontology support. So that users can supply static and dynamic
>> constraints to the properties they define on a class.
>>
>> It's currently touch and go if either of these will make it into 5.0, I'm
>> really hoping that we can do the later solution, but we currently have many
>> more priorities :(
>>
>>
>> Mark
>> Godmar Back wrote:
>> On Feb 20, 2008 12:30 PM, Edson Tirelli <tirelli at post.com> wrote:
>>
>>
>> Godmar,
>>
>> Shadow Facts are a necessary evil in current version. Basically what they
>> do is keep the working memory consistent in face of attribute changes on the
>> facts, that may happen both internally and externally to the working memory.
>> Our implementation to shadow facts is a lazy proxy that caches the
>> values until a safe point to synchronize the actual attribute value with the
>> one seen by the engine.
>>
>> So, the question is: given an object:
>>
>> (Map) fact
>>
>> How can we create an identical copy of it (shadow), if there is no
>> "clone" operation?
>>
>> Can you explain why you require the use of "clone()"?
>>
>> Cloning a map is otherwise easy - it's also referred to as a "shallow
>> copy" -- HashMap's HashMap(Map) constructor will do it.
>> http://java.sun.com/j2se/1.4.2/docs/api/java/util/HashMap.html#HashMap(java.util.Map)
>> I know you know that, so explain what necessitates the use of clone().
>>
>>
>>
>> More than that, the shadow must be a subclass of it.
>>
>> java.util.HashMap is a subclass of Map.
>>
>>
>>
>> Most Collection and Map implementations have a single parameter
>> constructor that allows us to do:
>>
>>
>> proxy = (ShadowProxy) this.shadowClass.getConstructor( new Class[]{cls}
>> ).newInstance( new Object[]{fact} );
>>
>> But the SingletonMap you were using does not accept that constructor.
>> So, one way is to explicit check if the fact is a SingletonMap and handle it
>> accordingly, but that is a specific class hack... is there any general
>> solution we can use?
>>
>>
>> Forget about the SingletonMap. That was just one of the many things I
>> tried and failed.
>>
>> Fundamentally, I would like Drools to process facts that were obtained
>> from real-world sources, and these facts have properties I do not know
>> in advance. Therefore, I cannot use beans (or using beans would be
>> highly inconvenient since it will require changes to Java code
>> whenever I'm referring to a new property, something I'd rather avoid.)
>>
>> - Godmar
>>
>>
>>
>> []s
>> Edson
>>
>> 2008/2/20, Godmar Back <godmar at gmail.com>:
>>
>>
>> I don't really understand what you mean by "shadow". What is the
>> purpose of such shadowing. Mark's email implies that it has to do with
>> concurrency protection; it's not clear what that means.
>>
>> In my view, whatever purpose you pursue with "shadowing", it does not
>> justify treating beans and maps differently.
>>
>> Your example of class Person shows that. If a person has two
>> attributes, name and age, then this is equivalent to a map with two
>> keys 'name' and 'age'.
>>
>> Here's the mapping:
>>
>> p.getName() corresponds to m["name"]
>> p.getAge() corresponds to m["age"]
>>
>> and setName/setAge accordingly.
>>
>> Mathematically, a bean is an associative array with a fixed set of
>> keys (called "properties") that map to values. For all practical
>> purposes, that is the same as a map. There's no reason to treat them
>> differently. Wherever you'd do "getXXX()" with a bean you'd do
>> .get("XXX") with a map.
>>
>> - Godmar
>>
>> On Feb 20, 2008 11:25 AM, Edson Tirelli <tirelli at post.com> wrote:
>>
>>
>> Ok, let me show one example. Imagine the class Person, with 2
>>
>> attributes
>>
>>
>>
>> (name and age) and the corresponding getter/setters.
>> What are the data for that fact that must be shadowed? easy answer:
>>
>> just
>>
>>
>>
>> shadow all getXXX() methods (getName and getAge).
>>
>> Now, take a Map. What is the data that must be shadowed?
>>
>> So, we do our best to work with facts that don't follow the javabean
>> spec, but collections and maps are a complicated beast. Again, if you
>>
>> have
>>
>>
>>
>> suggestions on how to improve the current support we provide for them,
>> please share with us.
>>
>> []s
>> Edson
>>
>> 2008/2/20, Godmar Back <godmar at gmail.com>:
>>
>>
>>
>> On Feb 20, 2008 9:23 AM, Edson Tirelli <tirelli at post.com> wrote:
>>
>>
>> Godmar,
>>
>> Short answer: collection/maps objects are not javabeans.
>>
>>
>> Explain why this is a problem.
>>
>> What is it about JavaBeans that your algorithm relies upon? Is it the
>> fact that the set of properties remains fixed and can be determined at
>> (fact) insertion time via reflection?
>>
>> Otherwise, I do not see any conceptual difference between a map and a
>>
>> bean.
>>
>>
>> If that is the difference, then please allow maps with an immutable
>>
>> key
>>
>>
>>
>> set.
>>
>>
>> - Godmar
>>
>>
>>
>>
>> Long answer: collection/maps must be shadowed to ensure
>>
>> consistency
>>
>>
>>
>>
>>
>> during execution, but how can we shadow the data if it is not
>>
>> exposed in
>>
>>
>>
>> a
>>
>>
>>
>> default, spec manner, as in javabeans? The algorithm we have in
>>
>> place
>>
>>
>>
>> right
>>
>>
>>
>> now is bellow. As you can see, it is a weak algo, but was the best I
>>
>> could
>>
>>
>>
>> come up at that time. If you have any suggestions on how to improve
>>
>> that, I
>>
>>
>>
>> appreciate.
>>
>> public Object getShadow(final Object fact) throws
>>
>> RuntimeDroolsException
>>
>>
>>
>> {
>> ShadowProxy proxy = null;
>> if ( isShadowEnabled() ) {
>> try {
>> if ( Collection.class.isAssignableFrom(
>>
>> this.shadowClass
>>
>>
>>
>> )
>>
>>
>>
>> || Map.class.isAssignableFrom( this.shadowClass ) ) {
>> // if it is a collection, try to instantiate
>>
>> using
>>
>>
>>
>>
>>
>> constructor
>> try {
>> proxy = (ShadowProxy)
>> this.shadowClass.getConstructor( new Class[]{cls} ).newInstance( new
>> Object[]{fact} );
>> } catch ( Exception e ) {
>> // not possible to instantiate using
>>
>> constructor
>>
>>
>>
>>
>>
>> }
>> }
>> if ( proxy == null ) {
>> if ( this.instantiator == null ) {
>> this.setInstantiator();
>> }
>> proxy = (ShadowProxy)
>>
>> this.instantiator.newInstance();
>>
>>
>>
>> }
>>
>> proxy.setShadowedObject( fact );
>> } catch ( final Exception e ) {
>> System.out.println( "shadow: " +proxy.getClass() +
>>
>> ":" +
>>
>>
>>
>>
>>
>> fact.getClass() );
>> throw new RuntimeDroolsException( "Error creating
>>
>> shadow
>>
>>
>>
>>
>>
>> fact for object: " + fact,
>> e );
>> }
>> }
>> return proxy;
>>
>>
>> }
>>
>> []s
>> Edson
>>
>> 2008/2/19, Godmar Back <godmar at gmail.com>:
>>
>>
>> As a general comment, the examples for which I find Drools failing
>>
>> are
>>
>>
>>
>>
>>
>>
>> not the actual examples for which my application is failing. It's
>>
>> just
>>
>>
>>
>>
>>
>>
>> the smallest test case I was able to eliminate.
>>
>> I'm now a bit concerned about your comment that Maps and
>>
>> Collections
>>
>>
>>
>>
>>
>>
>> aren't well-defined as Facts. I am planning to make extensive use
>>
>> of
>>
>>
>>
>>
>>
>>
>> them (that's also why I'd prefer to use the MVEL dialect, because
>>
>> in
>>
>>
>>
>>
>>
>>
>> Java I cannot do this without creating Bean wrappers.)
>>
>> Could you elaborate what makes the semantics not "well-defined".
>>
>> I'm specifically concerned with immutable maps (such as the one
>>
>> that
>>
>>
>>
>>
>>
>>
>> would have been returned by Collections.singletonMap), and with
>> collections of maps (such as those obtained via a "from"..."
>>
>> clause).
>>
>>
>>
>>
>>
>>
>> I need to insert immutable maps as facts; I understand that the
>>
>> items
>>
>>
>>
>>
>>
>>
>> returned by "from" aren't inserted as facts.
>>
>> - Godmar
>>
>> On Feb 19, 2008 3:11 PM, Edson Tirelli <tirelli at post.com> wrote:
>>
>>
>> Drools tries to create the ShadowProxy. The reason is that it
>>
>> does
>>
>>
>>
>> not
>>
>>
>>
>> know about the implementation... it just knows it is a Map and
>>
>> as
>>
>>
>>
>> so, it
>>
>>
>>
>>
>>
>> must be shadowed. Problem is that SingletonMap is either final
>>
>> or
>>
>>
>>
>> does
>>
>>
>>
>> not
>>
>>
>>
>> have a default constructor.
>> My recommendation, besides opening a JIRA for this, is avoid
>>
>> inserting
>>
>>
>>
>> collections/maps directly as facts. The semantic for such facts
>>
>> is
>>
>>
>>
>> not
>>
>>
>>
>>
>>
>> clearly defined and it may cause undesired behavior.
>>
>> []s
>> Edson
>>
>> 2008/2/19, Godmar Back <godmar at gmail.com>:
>>
>>
>> Hi,
>>
>> usings Drools 4.0.4 and MVEL 1.4, this simple rule:
>> ---
>> package test;
>>
>> import java.util.Collections;
>>
>> dialect "mvel"
>>
>> rule "Rule #1"
>> when
>> then
>> insert(Collections.singletonMap("content", "hello"));
>> end
>> --
>>
>> produces:
>> java.lang.IllegalAccessError: class
>>
>>
>> org.drools.shadow.java.util.Collections$SingletonMapShadowProxy
>>
>>
>>
>> cannot
>>
>>
>>
>>
>>
>>
>> access its superclass java.util.Collections$SingletonMap
>> at java.lang.ClassLoader.defineClass1(Native Method)
>> at
>>
>> java.lang.ClassLoader.defineClass(ClassLoader.java:620)
>>
>>
>>
>>
>>
>>
>>
>>
>> at
>>
>>
>> org.drools.rule.MapBackedClassLoader.fastFindClass(MapBackedClassLoader.java:60)
>>
>>
>>
>>
>>
>>
>>
>>
>> at
>>
>>
>> org.drools.rule.MapBackedClassLoader.loadClass(MapBackedClassLoader.java:79)
>>
>>
>>
>>
>>
>>
>>
>>
>> at
>>
>> java.lang.ClassLoader.loadClass(ClassLoader.java:251)
>>
>>
>>
>>
>>
>>
>>
>>
>> at
>>
>>
>> org.drools.reteoo.Rete$ClassObjectTypeConf.loadOrGenerateProxy(Rete.java:547)
>>
>>
>>
>>
>>
>>
>>
>>
>> at
>>
>>
>> org.drools.reteoo.Rete$ClassObjectTypeConf.defineShadowProxyData(Rete.java:494)
>>
>>
>>
>>
>>
>>
>>
>>
>> at
>>
>> org.drools.reteoo.Rete$ClassObjectTypeConf.<init>(Rete.java:461)
>>
>>
>> at org.drools.reteoo.Rete.assertObject(Rete.java:152)
>> at
>>
>> org.drools.reteoo.ReteooRuleBase.assertObject(ReteooRuleBase.java:192)
>>
>>
>>
>>
>>
>>
>> at
>>
>> org.drools.reteoo.ReteooWorkingMemory.doInsert(ReteooWorkingMemory.java:71)
>>
>>
>>
>>
>>
>>
>>
>>
>> at
>>
>>
>> org.drools.common.AbstractWorkingMemory.insert(AbstractWorkingMemory.java:909)
>>
>>
>>
>>
>>
>>
>>
>>
>> at
>>
>>
>> org.drools.common.AbstractWorkingMemory.insert(AbstractWorkingMemory.java:881)
>>
>>
>>
>>
>>
>>
>>
>>
>> at
>>
>>
>> org.drools.base.DefaultKnowledgeHelper.insert(DefaultKnowledgeHelper.java:67)
>>
>>
>>
>>
>>
>>
>>
>>
>> at
>>
>>
>> org.drools.base.DefaultKnowledgeHelper.insert(DefaultKnowledgeHelper.java:61)
>>
>>
>>
>>
>>
>>
>>
>>
>> It's not clear to me why Drools creates Proxies for such
>>
>> classes
>>
>>
>>
>> as
>>
>>
>>
>>
>>
>>
>> java.util.Collections, or does MVEL do it?
>>
>> - Godmar
>> _______________________________________________
>> rules-users mailing list
>> rules-users at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/rules-users
>>
>>
>> --
>> Edson Tirelli
>> JBoss Drools Core Development
>> Office: +55 11 3529-6000
>> Mobile: +55 11 9287-5646
>> JBoss, a division of Red Hat @ www.jboss.com
>> _______________________________________________
>> rules-users mailing list
>> rules-users at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/rules-users
>>
>>
>>
>> _______________________________________________
>> rules-users mailing list
>> rules-users at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/rules-users
>>
>>
>> --
>> Edson Tirelli
>> JBoss Drools Core Development
>> Office: +55 11 3529-6000
>> Mobile: +55 11 9287-5646
>> JBoss, a division of Red Hat @ www.jboss.com
>> _______________________________________________
>> rules-users mailing list
>> rules-users at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/rules-users
>>
>>
>>
>> _______________________________________________
>> rules-users mailing list
>> rules-users at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/rules-users
>>
>>
>>
>> --
>> Edson Tirelli
>> JBoss Drools Core Development
>> Office: +55 11 3529-6000
>> Mobile: +55 11 9287-5646
>> JBoss, a division of Red Hat @ www.jboss.com
>> _______________________________________________
>> rules-users mailing list
>> rules-users at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/rules-users
>>
>>
>>
>> _______________________________________________
>> rules-users mailing list
>> rules-users at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/rules-users
>>
>>
>> --
>> Edson Tirelli
>> JBoss Drools Core Development
>> Office: +55 11 3529-6000
>> Mobile: +55 11 9287-5646
>> JBoss, a division of Red Hat @ www.jboss.com
>> _______________________________________________
>> rules-users mailing list
>> rules-users at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/rules-users
>>
>>
>>
>> _______________________________________________
>> rules-users mailing list
>> rules-users at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/rules-users
>>
>>
>>
>> ________________________________
>>
>>
>> _______________________________________________
>> rules-users mailing list
>> rules-users at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/rules-users
>>
>>
>>
>> _______________________________________________
>> rules-users mailing list
>> rules-users at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/rules-users
>>
>>
>>
> _______________________________________________
> rules-users mailing list
> rules-users at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/rules-users
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/rules-users/attachments/20080221/f2f76163/attachment.html
More information about the rules-users
mailing list