[rules-users] IllegalAccessError in shadow classes
Godmar Back
godmar at gmail.com
Wed Feb 20 13:01:53 EST 2008
PS: I think I know where the confusion lies.
You consider maps just another kind of Java object you attempt to
treat like you would treat other objects - by examining their member
fields and methods, constructors, etc.
I was under the impression that instances of java.util.Maps would be
treated specially by your engine, i.e., as a collection of properties.
I concluded that since in the MVEL dialect you allow the use of the []
operator in a LHS. It seemed the straightforward thing to do, given
the conceptual equivalency of beans and (fixed-keyset) maps.
Maybe I should rephrase my question then. How do I work with facts for
which the set of properties is not known when I compile the Java
portions of the program in which I'm embedding my Drools rules?
- Godmar
On Wed, Feb 20, 2008 at 12:53 PM, Godmar Back <godmar at gmail.com> 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
> >
> >
>
More information about the rules-users
mailing list