<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
  <title></title>
</head>
<body bgcolor="#ffffff" text="#000000">
Godmar Back wrote:
<blockquote
 cite="mid:719dced30802201856m783763a7r536649cb5362d66f@mail.gmail.com"
 type="cite">
  <pre wrap="">Now that I read Ed's post, I realize I can simply turn shadowing off.
I don't use facts whose attributes change (*).

 - Godmar

(*) This probably shows my ignorance here - I freely admit the last
time I used expert systems before the current exercise was during an
AI class in college in the 90s - but why do systems such as Drools
support modifiable facts in the first place? If  facts become invalid,
they should be retracted and new facts be provided, </pre>
</blockquote>
This is why we need shadow proxies. If a fact becomes invalid, i.e. a
field has changed outside of a rule modify(....) block, we need the
original data to be able to retract the object. This retract limitation
has been removed in my 5.0 branch.<br>
<br>
However if someone modifies a field outside of the engine and doesn't
notify the engine, even though we still have the capabilities to
retract without shadow proxies in 5.0, they would still leave the
engine in an invalid state until it was removed.<br>
<blockquote
 cite="mid:719dced30802201856m783763a7r536649cb5362d66f@mail.gmail.com"
 type="cite">
  <pre wrap="">but why support
changing a fact literally "after the fact," if you pardon the pun?
  </pre>
</blockquote>
It's the horrors of integrating with java environments. Ideally users
will not modify facts outside of the engine, and will always use a
modify(...) block inside the engine - which then makes all of the above
a non issue. However there are many cases where modifications are done
outside of the engine, not ideal but it happens, so we need to provide
mechanisms to support this.<br>
<blockquote
 cite="mid:719dced30802201856m783763a7r536649cb5362d66f@mail.gmail.com"
 type="cite">
  <pre wrap="">Ed's example with person.likes changing from cheese to chocolate is
particularly telling, because such as change would - in common
parlance - be considered a change of opinion rather than a changing of
facts.
  </pre>
</blockquote>
Michael and I are big advocates of immutable models, it makes code much
more maintainable in the long run. But we can't enforce our best
practices on everyone, and some times its not possible so you just have
to get down and dirty. So again its a matter of us allowing the system
to work to the users use cases, rather than enforcing a particularly
development paradigm.<br>
<br>
I'm hoping that the removal of shadow facts as default in 5.0 will make
this a none issue. We will continue to support the ShadowProxy
implementation for those that need the feature of allowing external
changes while keeping the engine integrity valid, but we will push the
maintenance of this out to that person.<br>
<blockquote
 cite="mid:719dced30802201856m783763a7r536649cb5362d66f@mail.gmail.com"
 type="cite">
  <pre wrap="">
On Wed, Feb 20, 2008 at 9:40 PM, Mark Proctor <a class="moz-txt-link-rfc2396E" href="mailto:mproctor@codehaus.org">&lt;mproctor@codehaus.org&gt;</a> wrote:
  </pre>
  <blockquote type="cite">
    <pre wrap=""> If you want to use FactTemplates as a temporary, unsupported approach, feel
free. There are unit tests that show how this work.

 Btw when you use MVEL notation to access nested objects, like you do with a
Map, we just re-write it as an eval. This means you won't get any of the
indexing performance. You can still get indexing if you represent your facts
with FactTemplates.

 Mark
 Mark Proctor wrote:

 Personally I don't like the idea of a Map as a model as it has no type, so
straight away you lose object level descrimination. Also a Map is not
declarative in defining what it is you are reasoning over. It's a hack to
get over the limitations of the current environment.

 In the engine we have something called FactTemplats, which we do not
currently document - it's a hidden feature. These work much less Jess
Deftemplates, and where infact made so that we could support a Jess/clips.
The implementation is basically an array and uses name tokenising to get
access. i.e. you write person.name == "Godmar" and we rewrite it as
person.setField( 0, "Godmar" ). Although we haven't yet got the rewritting
part done so currently you have to manually do the above, or make it lookup
the position each time with person.setField( "name", "Godmar" ). These
FactTemplates can be reasoned over in the LHS just like pojos.

 However I'm not currently happy with the solution and thinking instead of
going down the route of runtime bean generation. This would allow you to
define models at runtime, without caring about the underlying
implementation, and still give us pojos to work with and also provides more
performance. further to this we really want to do our model implementation
with ontology support. So that users can supply static and dynamic
constraints to the properties they define on a class.

 It's currently touch and go if either of these will make it into 5.0, I'm
really hoping that we can do the later solution, but we currently have many
more priorities :(


 Mark
 Godmar Back wrote:
 On Feb 20, 2008 12:30 PM, Edson Tirelli <a class="moz-txt-link-rfc2396E" href="mailto:tirelli@post.com">&lt;tirelli@post.com&gt;</a> 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.
<a class="moz-txt-link-freetext" href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/HashMap.html#HashMap(java.util.Map)">http://java.sun.com/j2se/1.4.2/docs/api/java/util/HashMap.html#HashMap(java.util.Map)</a>
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 <a class="moz-txt-link-rfc2396E" href="mailto:godmar@gmail.com">&lt;godmar@gmail.com&gt;</a>:


 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:


 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>:



 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:


 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 <a class="moz-txt-link-rfc2396E" href="mailto:godmar@gmail.com">&lt;godmar@gmail.com&gt;</a>:


 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:


 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 <a class="moz-txt-link-rfc2396E" href="mailto:godmar@gmail.com">&lt;godmar@gmail.com&gt;</a>:


 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.&lt;init&gt;(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
<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>


 --
 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>



 _______________________________________________
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>


 --
 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>



 _______________________________________________
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>



--
 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>



 _______________________________________________
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>


 --
 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>



 _______________________________________________
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>



 ________________________________


_______________________________________________
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>



_______________________________________________
 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>