<br> Ok, let me show one example. Imagine the class Person, with 2 attributes (name and age) and the corresponding getter/setters.<br> What are the data for that fact that must be shadowed? easy answer: just shadow all getXXX() methods (getName and getAge).<br>
<br> Now, take a Map. What is the data that must be shadowed?<br><br> 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.<br>
<br> []s<br> Edson<br><br><div><span class="gmail_quote">2008/2/20, Godmar Back <<a href="mailto:godmar@gmail.com">godmar@gmail.com</a>>:</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
On Feb 20, 2008 9:23 AM, Edson Tirelli <<a href="mailto:tirelli@post.com">tirelli@post.com</a>> wrote:<br>><br>> Godmar,<br>><br>> Short answer: collection/maps objects are not javabeans.<br>><br>
<br>Explain why this is a problem.<br><br>What is it about JavaBeans that your algorithm relies upon? Is it the<br>fact that the set of properties remains fixed and can be determined at<br>(fact) insertion time via reflection?<br>
<br>Otherwise, I do not see any conceptual difference between a map and a bean.<br>If that is the difference, then please allow maps with an immutable key set.<br><br> - Godmar<br><br><br>> Long answer: collection/maps must be shadowed to ensure consistency<br>
> during execution, but how can we shadow the data if it is not exposed in a<br>> default, spec manner, as in javabeans? The algorithm we have in place right<br>> now is bellow. As you can see, it is a weak algo, but was the best I could<br>
> come up at that time. If you have any suggestions on how to improve that, I<br>> appreciate.<br>><br>> public Object getShadow(final Object fact) throws RuntimeDroolsException<br>> {<br>> ShadowProxy proxy = null;<br>
> if ( isShadowEnabled() ) {<br>> try {<br>> if ( Collection.class.isAssignableFrom( this.shadowClass )<br>> || Map.class.isAssignableFrom( this.shadowClass ) ) {<br>> // if it is a collection, try to instantiate using<br>
> constructor<br>> try {<br>> proxy = (ShadowProxy)<br>> this.shadowClass.getConstructor( new Class[]{cls} ).newInstance( new<br>> Object[]{fact} );<br>> } catch ( Exception e ) {<br>
> // not possible to instantiate using constructor<br>> }<br>> }<br>> if ( proxy == null ) {<br>> if ( this.instantiator == null ) {<br>
> this.setInstantiator();<br>> }<br>> proxy = (ShadowProxy) this.instantiator.newInstance();<br>> }<br>><br>> proxy.setShadowedObject( fact );<br>
> } catch ( final Exception e ) {<br>> System.out.println( "shadow: " +proxy.getClass() + ":" +<br>> fact.getClass() );<br>> throw new RuntimeDroolsException( "Error creating shadow<br>
> fact for object: " + fact,<br>> e );<br>> }<br>> }<br>> return proxy;<br>><br>><br>> }<br>><br>> []s<br>
> Edson<br>><br>> 2008/2/19, Godmar Back <<a href="mailto:godmar@gmail.com">godmar@gmail.com</a>>:<br>> > As a general comment, the examples for which I find Drools failing are<br>> > not the actual examples for which my application is failing. It's just<br>
> > the smallest test case I was able to eliminate.<br>> ><br>> > I'm now a bit concerned about your comment that Maps and Collections<br>> > aren't well-defined as Facts. I am planning to make extensive use of<br>
> > them (that's also why I'd prefer to use the MVEL dialect, because in<br>> > Java I cannot do this without creating Bean wrappers.)<br>> ><br>> > Could you elaborate what makes the semantics not "well-defined".<br>
> ><br>> > I'm specifically concerned with immutable maps (such as the one that<br>> > would have been returned by Collections.singletonMap), and with<br>> > collections of maps (such as those obtained via a "from"..." clause).<br>
> > I need to insert immutable maps as facts; I understand that the items<br>> > returned by "from" aren't inserted as facts.<br>> ><br>> > - Godmar<br>> ><br>> > On Feb 19, 2008 3:11 PM, Edson Tirelli <<a href="mailto:tirelli@post.com">tirelli@post.com</a>> wrote:<br>
> > ><br>> > > Drools tries to create the ShadowProxy. The reason is that it does<br>> not<br>> > > know about the implementation... it just knows it is a Map and as so, it<br>> > > must be shadowed. Problem is that SingletonMap is either final or does<br>
> not<br>> > > have a default constructor.<br>> > > My recommendation, besides opening a JIRA for this, is avoid<br>> inserting<br>> > > collections/maps directly as facts. The semantic for such facts is not<br>
> > > clearly defined and it may cause undesired behavior.<br>> > ><br>> > > []s<br>> > > Edson<br>> > ><br>> > > 2008/2/19, Godmar Back <<a href="mailto:godmar@gmail.com">godmar@gmail.com</a>>:<br>
> > > ><br>> > > ><br>> > > ><br>> > > > Hi,<br>> > > ><br>> > > > usings Drools 4.0.4 and MVEL 1.4, this simple rule:<br>> > > > ---<br>
> > > > package test;<br>> > > ><br>> > > > import java.util.Collections;<br>> > > ><br>> > > > dialect "mvel"<br>> > > ><br>> > > > rule "Rule #1"<br>
> > > > when<br>> > > > then<br>> > > > insert(Collections.singletonMap("content", "hello"));<br>> > > > end<br>> > > > --<br>> > > ><br>
> > > > produces:<br>> > > > java.lang.IllegalAccessError: class<br>> > > > org.drools.shadow.java.util.Collections$SingletonMapShadowProxy cannot<br>> > > > access its superclass java.util.Collections$SingletonMap<br>
> > > > at java.lang.ClassLoader.defineClass1(Native Method)<br>> > > > at java.lang.ClassLoader.defineClass(ClassLoader.java:620)<br>> > > > at<br>> > ><br>
> org.drools.rule.MapBackedClassLoader.fastFindClass(MapBackedClassLoader.java:60)<br>> > > > at<br>> > ><br>> org.drools.rule.MapBackedClassLoader.loadClass(MapBackedClassLoader.java:79)<br>
> > > > at java.lang.ClassLoader.loadClass(ClassLoader.java:251)<br>> > > > at<br>> > ><br>> org.drools.reteoo.Rete$ClassObjectTypeConf.loadOrGenerateProxy(Rete.java:547)<br>
> > > > at<br>> > ><br>> org.drools.reteoo.Rete$ClassObjectTypeConf.defineShadowProxyData(Rete.java:494)<br>> > > > at<br>> > > org.drools.reteoo.Rete$ClassObjectTypeConf.<init>(Rete.java:461)<br>
> > > > at org.drools.reteoo.Rete.assertObject(Rete.java:152)<br>> > > > at<br>> > > org.drools.reteoo.ReteooRuleBase.assertObject(ReteooRuleBase.java:192)<br>> > > > at<br>
> > ><br>> org.drools.reteoo.ReteooWorkingMemory.doInsert(ReteooWorkingMemory.java:71)<br>> > > > at<br>> > ><br>> org.drools.common.AbstractWorkingMemory.insert(AbstractWorkingMemory.java:909)<br>
> > > > at<br>> > ><br>> org.drools.common.AbstractWorkingMemory.insert(AbstractWorkingMemory.java:881)<br>> > > > at<br>> > ><br>> org.drools.base.DefaultKnowledgeHelper.insert(DefaultKnowledgeHelper.java:67)<br>
> > > > at<br>> > ><br>> org.drools.base.DefaultKnowledgeHelper.insert(DefaultKnowledgeHelper.java:61)<br>> > > ><br>> > > ><br>> > > > It's not clear to me why Drools creates Proxies for such classes as<br>
> > > > java.util.Collections, or does MVEL do it?<br>> > > ><br>> > > > - Godmar<br>> > > > _______________________________________________<br>> > > > rules-users mailing list<br>
> > > > <a href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a><br>> > > > <a href="https://lists.jboss.org/mailman/listinfo/rules-users">https://lists.jboss.org/mailman/listinfo/rules-users</a><br>
> > > ><br>> > ><br>> > ><br>> > ><br>> > > --<br>> > > Edson Tirelli<br>> > > JBoss Drools Core Development<br>> > > Office: +55 11 3529-6000<br>
> > > Mobile: +55 11 9287-5646<br>> > > JBoss, a division of Red Hat @ <a href="http://www.jboss.com">www.jboss.com</a><br>> > > _______________________________________________<br>> > > rules-users mailing list<br>
> > > <a href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a><br>> > > <a href="https://lists.jboss.org/mailman/listinfo/rules-users">https://lists.jboss.org/mailman/listinfo/rules-users</a><br>
> > ><br>> > ><br>> > _______________________________________________<br>> > rules-users mailing list<br>> > <a href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a><br>
> > <a href="https://lists.jboss.org/mailman/listinfo/rules-users">https://lists.jboss.org/mailman/listinfo/rules-users</a><br>> ><br>><br>><br>><br>> --<br>> Edson Tirelli<br>> JBoss Drools Core Development<br>
> Office: +55 11 3529-6000<br>> Mobile: +55 11 9287-5646<br>> JBoss, a division of Red Hat @ <a href="http://www.jboss.com">www.jboss.com</a><br>> _______________________________________________<br>> rules-users mailing list<br>
> <a href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a><br>> <a href="https://lists.jboss.org/mailman/listinfo/rules-users">https://lists.jboss.org/mailman/listinfo/rules-users</a><br>><br>
><br>_______________________________________________<br>rules-users mailing list<br><a href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a><br><a href="https://lists.jboss.org/mailman/listinfo/rules-users">https://lists.jboss.org/mailman/listinfo/rules-users</a><br>
</blockquote></div><br><br clear="all"><br>-- <br> Edson Tirelli<br> JBoss Drools Core Development<br> Office: +55 11 3529-6000<br> Mobile: +55 11 9287-5646<br> JBoss, a division of Red Hat @ <a href="http://www.jboss.com">www.jboss.com</a>