[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