<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
</head>
<body bgcolor="#ffffff" text="#000000">
Drools 4.x assert/retracts, like Jess, are symmetrical. When you assert
the data it uses the constraints to determine the cross product joins
which controls the propagation throughout the network. When you do a
retract it uses those same constraints todetermine the cross product
joins to be able to propagate through the graph removing itself from
the node memories where the assert propagation reached before.<br>
<br>
Now if we go back to standard Java when you have a HashMap with a
key/value pair, if you put an object into the map and changed a field
on the key that changes the hashcode/equals methods you will never be
able to retrieve the object. It is the same for us, the working memory
has lots and lots of hash maps.<br>
<br>
Now what happens when you modify a bean? a modify is actually a
retract+assert so when you call update(...) after the field has changed
how can the retract correct determine all the nodes where the object is
remembered? It can't as the information is no longer there to determine
this. To get around this we have to shadow a bean, i.e. make a copy of
all the bean's fields on insertion. When you call update() the engine
still sees the old field values, even though they might have been
updated on the source object. This allows the retract to always behave
symmetrically to the assert.<br>
<br>
With Maps and thus nested objects shadowing becomes very hard. As we
would have to shadow the entire map and then shadow evey object in that
map. Which is far from ideal. This is also why with 4.0 you must be
extremely careful with nested objects, which we recommend are immutable
while the parent object lives in the network, shadowing an entire
object graph is simply not practical.<br>
<br>
In Drools 3.0 we did not need to shadow as we hade a more complicated
algorithm that maintained more references allowing for asymetrical
behaviour - however I couldn't get the algorithm to perform with Jess
like performance and it used a lot more memory. I dropped Drools 4.0
back to how Jess does it with shadow facts and symmetrical
assert/retract. For Drools 5.0 I have re-written the algorithm and have
managed to get asymettrical behaviour with actual performance
increases, not losses. This is now in a branch and I hope to merge into
trunk soon.<br>
<br>
After this the only reason someone would want shadow proxies is to
protect an object that is currently in the working memory from field
modifications leaving the network integrity invalid. i.e. if another
thread changes the field on an object in the working memory and the wm
is not correctly notified we have an object cached in a state that it
no longer represents, this will make all join attempts invalid until
the engine is notified and the object is re-propagated throughout the
network. As 5.0 will no longer require shadow proxies by default we
will propably remove the asm proxy implementation we have and instead
just have an interface and leave the implementation of this to the
user, probably using aop. This will simplify our engine, and help
performance a little, so that we offload the solution to problem to
those that need it.<br>
<br>
Mark<br>
<br>
Godmar Back wrote:
<blockquote
 cite="mid:719dced30802200840j15c21dd1p7724887d4c4a7cab@mail.gmail.com"
 type="cite">
  <pre wrap="">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 <a class="moz-txt-link-rfc2396E" href="mailto:tirelli@post.com">&lt;tirelli@post.com&gt;</a> wrote:
  </pre>
  <blockquote type="cite">
    <pre wrap="">   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 <a class="moz-txt-link-rfc2396E" href="mailto:godmar@gmail.com">&lt;godmar@gmail.com&gt;</a>:

    </pre>
    <blockquote type="cite">
      <pre wrap="">On Feb 20, 2008 9:23 AM, Edson Tirelli <a class="moz-txt-link-rfc2396E" href="mailto:tirelli@post.com">&lt;tirelli@post.com&gt;</a> wrote:
      </pre>
      <blockquote type="cite">
        <pre wrap="">   Godmar,

   Short answer: collection/maps objects are not javabeans.

        </pre>
      </blockquote>
      <pre wrap="">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
      </pre>
    </blockquote>
    <pre wrap="">bean.
    </pre>
    <blockquote type="cite">
      <pre wrap="">If that is the difference, then please allow maps with an immutable key
      </pre>
    </blockquote>
    <pre wrap="">set.
    </pre>
    <blockquote type="cite">
      <pre wrap="">- Godmar


      </pre>
      <blockquote type="cite">
        <pre wrap="">   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
        </pre>
      </blockquote>
    </blockquote>
    <pre wrap="">a
    </pre>
    <blockquote type="cite">
      <blockquote type="cite">
        <pre wrap="">default, spec manner, as in javabeans? The algorithm we have in place
        </pre>
      </blockquote>
    </blockquote>
    <pre wrap="">right
    </pre>
    <blockquote type="cite">
      <blockquote type="cite">
        <pre wrap="">now is bellow. As you can see, it is a weak algo, but was the best I
        </pre>
      </blockquote>
    </blockquote>
    <pre wrap="">could
    </pre>
    <blockquote type="cite">
      <blockquote type="cite">
        <pre wrap="">come up at that time. If you have any suggestions on how to improve
        </pre>
      </blockquote>
    </blockquote>
    <pre wrap="">that, I
    </pre>
    <blockquote type="cite">
      <blockquote type="cite">
        <pre wrap="">appreciate.

    public Object getShadow(final Object fact) throws
        </pre>
      </blockquote>
    </blockquote>
    <pre wrap="">RuntimeDroolsException
    </pre>
    <blockquote type="cite">
      <blockquote type="cite">
        <pre wrap="">{
        ShadowProxy proxy = null;
        if ( isShadowEnabled() ) {
            try {
                if ( Collection.class.isAssignableFrom( this.shadowClass
        </pre>
      </blockquote>
    </blockquote>
    <pre wrap="">)
    </pre>
    <blockquote type="cite">
      <blockquote type="cite">
        <pre wrap="">|| 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)
        </pre>
      </blockquote>
    </blockquote>
    <pre wrap="">this.instantiator.newInstance();
    </pre>
    <blockquote type="cite">
      <blockquote type="cite">
        <pre wrap="">                }

                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 <a class="moz-txt-link-rfc2396E" href="mailto:godmar@gmail.com">&lt;godmar@gmail.com&gt;</a>:
        </pre>
        <blockquote type="cite">
          <pre wrap="">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 <a class="moz-txt-link-rfc2396E" href="mailto:tirelli@post.com">&lt;tirelli@post.com&gt;</a> wrote:
          </pre>
          <blockquote type="cite">
            <pre wrap="">   Drools tries to create the ShadowProxy. The reason is that it
            </pre>
          </blockquote>
        </blockquote>
      </blockquote>
    </blockquote>
    <pre wrap="">does
    </pre>
    <blockquote type="cite">
      <blockquote type="cite">
        <pre wrap="">not
        </pre>
        <blockquote type="cite">
          <blockquote type="cite">
            <pre wrap="">know about the implementation... it just knows it is a Map and as
            </pre>
          </blockquote>
        </blockquote>
      </blockquote>
    </blockquote>
    <pre wrap="">so, it
    </pre>
    <blockquote type="cite">
      <blockquote type="cite">
        <blockquote type="cite">
          <blockquote type="cite">
            <pre wrap="">must be shadowed. Problem is that SingletonMap is either  final or
            </pre>
          </blockquote>
        </blockquote>
      </blockquote>
    </blockquote>
    <pre wrap="">does
    </pre>
    <blockquote type="cite">
      <blockquote type="cite">
        <pre wrap="">not
        </pre>
        <blockquote type="cite">
          <blockquote type="cite">
            <pre wrap="">have a default constructor.
    My recommendation, besides opening a JIRA for this, is avoid
            </pre>
          </blockquote>
        </blockquote>
        <pre wrap="">inserting
        </pre>
        <blockquote type="cite">
          <blockquote type="cite">
            <pre wrap="">collections/maps directly as facts. The semantic for such facts is
            </pre>
          </blockquote>
        </blockquote>
      </blockquote>
    </blockquote>
    <pre wrap="">not
    </pre>
    <blockquote type="cite">
      <blockquote type="cite">
        <blockquote type="cite">
          <blockquote type="cite">
            <pre wrap="">clearly defined and it may cause undesired behavior.

   []s
   Edson

2008/2/19, Godmar Back <a class="moz-txt-link-rfc2396E" href="mailto:godmar@gmail.com">&lt;godmar@gmail.com&gt;</a>:
            </pre>
            <blockquote type="cite">
              <pre wrap="">

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
              </pre>
            </blockquote>
          </blockquote>
        </blockquote>
      </blockquote>
    </blockquote>
    <pre wrap="">cannot
    </pre>
    <blockquote type="cite">
      <blockquote type="cite">
        <blockquote type="cite">
          <blockquote type="cite">
            <blockquote type="cite">
              <pre wrap="">access its superclass java.util.Collections$SingletonMap
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:620)
        at
              </pre>
            </blockquote>
          </blockquote>
        </blockquote>
      </blockquote>
    </blockquote>
    <pre wrap="">org.drools.rule.MapBackedClassLoader.fastFindClass(MapBackedClassLoader.java:60)
    </pre>
    <blockquote type="cite">
      <blockquote type="cite">
        <blockquote type="cite">
          <blockquote type="cite">
            <blockquote type="cite">
              <pre wrap="">        at
              </pre>
            </blockquote>
          </blockquote>
        </blockquote>
      </blockquote>
    </blockquote>
    <pre wrap="">org.drools.rule.MapBackedClassLoader.loadClass(MapBackedClassLoader.java:79)
    </pre>
    <blockquote type="cite">
      <blockquote type="cite">
        <blockquote type="cite">
          <blockquote type="cite">
            <blockquote type="cite">
              <pre wrap="">        at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
        at
              </pre>
            </blockquote>
          </blockquote>
        </blockquote>
      </blockquote>
    </blockquote>
    <pre wrap="">org.drools.reteoo.Rete$ClassObjectTypeConf.loadOrGenerateProxy(Rete.java:547)
    </pre>
    <blockquote type="cite">
      <blockquote type="cite">
        <blockquote type="cite">
          <blockquote type="cite">
            <blockquote type="cite">
              <pre wrap="">        at
              </pre>
            </blockquote>
          </blockquote>
        </blockquote>
      </blockquote>
    </blockquote>
    <pre wrap="">org.drools.reteoo.Rete$ClassObjectTypeConf.defineShadowProxyData(Rete.java:494)
    </pre>
    <blockquote type="cite">
      <blockquote type="cite">
        <blockquote type="cite">
          <blockquote type="cite">
            <blockquote type="cite">
              <pre wrap="">        at
              </pre>
            </blockquote>
            <pre wrap="">org.drools.reteoo.Rete$ClassObjectTypeConf.&lt;init&gt;(Rete.java:461)
            </pre>
            <blockquote type="cite">
              <pre wrap="">        at org.drools.reteoo.Rete.assertObject(Rete.java:152)
        at
              </pre>
            </blockquote>
          </blockquote>
        </blockquote>
      </blockquote>
    </blockquote>
    <pre wrap="">org.drools.reteoo.ReteooRuleBase.assertObject(ReteooRuleBase.java:192)
    </pre>
    <blockquote type="cite">
      <blockquote type="cite">
        <blockquote type="cite">
          <blockquote type="cite">
            <blockquote type="cite">
              <pre wrap="">        at
              </pre>
            </blockquote>
          </blockquote>
        </blockquote>
      </blockquote>
    </blockquote>
    <pre wrap="">org.drools.reteoo.ReteooWorkingMemory.doInsert(ReteooWorkingMemory.java:71)
    </pre>
    <blockquote type="cite">
      <blockquote type="cite">
        <blockquote type="cite">
          <blockquote type="cite">
            <blockquote type="cite">
              <pre wrap="">        at
              </pre>
            </blockquote>
          </blockquote>
        </blockquote>
      </blockquote>
    </blockquote>
    <pre wrap="">org.drools.common.AbstractWorkingMemory.insert(AbstractWorkingMemory.java:909)
    </pre>
    <blockquote type="cite">
      <blockquote type="cite">
        <blockquote type="cite">
          <blockquote type="cite">
            <blockquote type="cite">
              <pre wrap="">        at
              </pre>
            </blockquote>
          </blockquote>
        </blockquote>
      </blockquote>
    </blockquote>
    <pre wrap="">org.drools.common.AbstractWorkingMemory.insert(AbstractWorkingMemory.java:881)
    </pre>
    <blockquote type="cite">
      <blockquote type="cite">
        <blockquote type="cite">
          <blockquote type="cite">
            <blockquote type="cite">
              <pre wrap="">        at
              </pre>
            </blockquote>
          </blockquote>
        </blockquote>
      </blockquote>
    </blockquote>
    <pre wrap="">org.drools.base.DefaultKnowledgeHelper.insert(DefaultKnowledgeHelper.java:67)
    </pre>
    <blockquote type="cite">
      <blockquote type="cite">
        <blockquote type="cite">
          <blockquote type="cite">
            <blockquote type="cite">
              <pre wrap="">        at
              </pre>
            </blockquote>
          </blockquote>
        </blockquote>
      </blockquote>
    </blockquote>
    <pre wrap="">org.drools.base.DefaultKnowledgeHelper.insert(DefaultKnowledgeHelper.java:61)
    </pre>
    <blockquote type="cite">
      <blockquote type="cite">
        <blockquote type="cite">
          <blockquote type="cite">
            <blockquote type="cite">
              <pre wrap="">
It's not clear to me why Drools creates Proxies for such classes
              </pre>
            </blockquote>
          </blockquote>
        </blockquote>
      </blockquote>
    </blockquote>
    <pre wrap="">as
    </pre>
    <blockquote type="cite">
      <blockquote type="cite">
        <blockquote type="cite">
          <blockquote type="cite">
            <blockquote type="cite">
              <pre wrap="">java.util.Collections, or does MVEL do it?

- Godmar
_______________________________________________
rules-users mailing list
<a class="moz-txt-link-abbreviated" href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a>
<a class="moz-txt-link-freetext" href="https://lists.jboss.org/mailman/listinfo/rules-users">https://lists.jboss.org/mailman/listinfo/rules-users</a>

              </pre>
            </blockquote>
            <pre wrap="">

--
  Edson Tirelli
  JBoss Drools Core Development
   Office: +55 11 3529-6000
  Mobile: +55 11 9287-5646
  JBoss, a division of Red Hat @ <a class="moz-txt-link-abbreviated" href="http://www.jboss.com">www.jboss.com</a>
_______________________________________________
rules-users mailing list
<a class="moz-txt-link-abbreviated" href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a>
<a class="moz-txt-link-freetext" href="https://lists.jboss.org/mailman/listinfo/rules-users">https://lists.jboss.org/mailman/listinfo/rules-users</a>


            </pre>
          </blockquote>
          <pre wrap="">_______________________________________________
rules-users mailing list
<a class="moz-txt-link-abbreviated" href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a>
<a class="moz-txt-link-freetext" href="https://lists.jboss.org/mailman/listinfo/rules-users">https://lists.jboss.org/mailman/listinfo/rules-users</a>

          </pre>
        </blockquote>
        <pre wrap="">

--
  Edson Tirelli
  JBoss Drools Core Development
  Office: +55 11 3529-6000
  Mobile: +55 11 9287-5646
  JBoss, a division of Red Hat @ <a class="moz-txt-link-abbreviated" href="http://www.jboss.com">www.jboss.com</a>
_______________________________________________
rules-users mailing list
<a class="moz-txt-link-abbreviated" href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a>
<a class="moz-txt-link-freetext" href="https://lists.jboss.org/mailman/listinfo/rules-users">https://lists.jboss.org/mailman/listinfo/rules-users</a>


        </pre>
      </blockquote>
      <pre wrap="">_______________________________________________
rules-users mailing list
<a class="moz-txt-link-abbreviated" href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a>
<a class="moz-txt-link-freetext" href="https://lists.jboss.org/mailman/listinfo/rules-users">https://lists.jboss.org/mailman/listinfo/rules-users</a>

      </pre>
    </blockquote>
    <pre wrap="">


--
  Edson Tirelli
  JBoss Drools Core Development
  Office: +55 11 3529-6000
  Mobile: +55 11 9287-5646
  JBoss, a division of Red Hat @ <a class="moz-txt-link-abbreviated" href="http://www.jboss.com">www.jboss.com</a>
_______________________________________________
rules-users mailing list
<a class="moz-txt-link-abbreviated" href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a>
<a class="moz-txt-link-freetext" href="https://lists.jboss.org/mailman/listinfo/rules-users">https://lists.jboss.org/mailman/listinfo/rules-users</a>


    </pre>
  </blockquote>
  <pre wrap=""><!---->_______________________________________________
rules-users mailing list
<a class="moz-txt-link-abbreviated" href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a>
<a class="moz-txt-link-freetext" href="https://lists.jboss.org/mailman/listinfo/rules-users">https://lists.jboss.org/mailman/listinfo/rules-users</a>

  </pre>
</blockquote>
<br>
</body>
</html>