On Feb 20, 2008 12:30 PM, Edson Tirelli <tirelli@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@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@post.com> wrote:Ok, let me show one example. Imagine the class Person, with 2attributes(name and age) and the corresponding getter/setters. What are the data for that fact that must be shadowed? easy answer:justshadow 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 youhavesuggestions on how to improve the current support we provide for them, please share with us. []s Edson 2008/2/20, Godmar Back <godmar@gmail.com>:On Feb 20, 2008 9:23 AM, Edson Tirelli <tirelli@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 abean.If that is the difference, then please allow maps with an immutablekeyset.- GodmarLong answer: collection/maps must be shadowed to ensureconsistencyduring execution, but how can we shadow the data if it is notexposed inadefault, spec manner, as in javabeans? The algorithm we have inplacerightnow is bellow. As you can see, it is a weak algo, but was the best Icouldcome up at that time. If you have any suggestions on how to improvethat, Iappreciate. public Object getShadow(final Object fact) throwsRuntimeDroolsException{ ShadowProxy proxy = null; if ( isShadowEnabled() ) { try { if ( Collection.class.isAssignableFrom(this.shadowClass)|| Map.class.isAssignableFrom( this.shadowClass ) ) { // if it is a collection, try to instantiateusingconstructor try { proxy = (ShadowProxy) this.shadowClass.getConstructor( new Class[]{cls} ).newInstance( new Object[]{fact} ); } catch ( Exception e ) { // not possible to instantiate usingconstructor} } 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 creatingshadowfact for object: " + fact, e ); } } return proxy; } []s Edson 2008/2/19, Godmar Back <godmar@gmail.com>:As a general comment, the examples for which I find Drools failingarenot the actual examples for which my application is failing. It'sjustthe smallest test case I was able to eliminate. I'm now a bit concerned about your comment that Maps andCollectionsaren't well-defined as Facts. I am planning to make extensive useofthem (that's also why I'd prefer to use the MVEL dialect, becauseinJava 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 onethatwould 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 theitemsreturned by "from" aren't inserted as facts. - Godmar On Feb 19, 2008 3:11 PM, Edson Tirelli <tirelli@post.com> wrote:Drools tries to create the ShadowProxy. The reason is that itdoesnotknow about the implementation... it just knows it is a Map andasso, itmust be shadowed. Problem is that SingletonMap is either finalordoesnothave a default constructor. My recommendation, besides opening a JIRA for this, is avoidinsertingcollections/maps directly as facts. The semantic for such factsisnotclearly defined and it may cause undesired behavior. []s Edson 2008/2/19, Godmar Back <godmar@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: classorg.drools.shadow.java.util.Collections$SingletonMapShadowProxycannotaccess its superclass java.util.Collections$SingletonMap at java.lang.ClassLoader.defineClass1(Native Method) atjava.lang.ClassLoader.defineClass(ClassLoader.java:620)atorg.drools.rule.MapBackedClassLoader.fastFindClass(MapBackedClassLoader.java:60)atorg.drools.rule.MapBackedClassLoader.loadClass(MapBackedClassLoader.java:79)atjava.lang.ClassLoader.loadClass(ClassLoader.java:251)atorg.drools.reteoo.Rete$ClassObjectTypeConf.loadOrGenerateProxy(Rete.java:547)atorg.drools.reteoo.Rete$ClassObjectTypeConf.defineShadowProxyData(Rete.java:494)atorg.drools.reteoo.Rete$ClassObjectTypeConf.<init>(Rete.java:461)at org.drools.reteoo.Rete.assertObject(Rete.java:152) atorg.drools.reteoo.ReteooRuleBase.assertObject(ReteooRuleBase.java:192)atorg.drools.reteoo.ReteooWorkingMemory.doInsert(ReteooWorkingMemory.java:71)atorg.drools.common.AbstractWorkingMemory.insert(AbstractWorkingMemory.java:909)atorg.drools.common.AbstractWorkingMemory.insert(AbstractWorkingMemory.java:881)atorg.drools.base.DefaultKnowledgeHelper.insert(DefaultKnowledgeHelper.java:67)atorg.drools.base.DefaultKnowledgeHelper.insert(DefaultKnowledgeHelper.java:61)It's not clear to me why Drools creates Proxies for suchclassesasjava.util.Collections, or does MVEL do it? - Godmar _______________________________________________ rules-users mailing list rules-users@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@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-users_______________________________________________ rules-users mailing list rules-users@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@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-users_______________________________________________ rules-users mailing list rules-users@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@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-users_______________________________________________ rules-users mailing list rules-users@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@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-users_______________________________________________ rules-users mailing list rules-users@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-users