[
http://jira.jboss.com/jira/browse/JBRULES-1115?page=comments#action_12373750 ]
Edson Tirelli commented on JBRULES-1115:
----------------------------------------
Ok, I did some debugging and the problem is indeed related to ShadowFacts. Let me first
show you my tests:
public void testShadowProxyOnCollections() throws Exception {
final PackageBuilder builder = new PackageBuilder();
builder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream(
"test_ShadowProxyOnCollections.drl" ) ) );
final Package pkg = builder.getPackage();
final RuleBase ruleBase = getRuleBase();
ruleBase.addPackage( pkg );
final WorkingMemory workingMemory = ruleBase.newStatefulSession();
final List results = new ArrayList();
workingMemory.setGlobal( "results",
results );
final Cheesery cheesery = new Cheesery();
workingMemory.insert( cheesery );
workingMemory.fireAllRules();
assertEquals( 1,
results.size() );
assertEquals( 1,
cheesery.getCheeses().size() );
assertEquals( results.get( 0 ),
cheesery.getCheeses().get( 0 ) );
}
If we use the following rule, there is no problem, since in the consequence, we unwrap the
shadow proxy, and what you get is your original object, where the Cheese is correctly
added to the Cheesery object.
package org.drools;
global java.util.List results;
rule "shadow proxy on collections"
when
$c : Cheesery()
then
Cheese cheese = new Cheese( "stilton", 10 );
$c.addCheese( cheese );
results.add( cheese );
end
Now, if we use "collect" to create a list, like in the following rule, what is
added to the list is the object with the shadow proxy wrapper. So, when it is extracted
from the list, you are using the shadow proxy and not the original object. There would be
no serious problem if you were not using a getXXX() method, because all other non-final
methods are delegated... only get methods are shadowed, and so, the getCheeses() method is
returning the shadowed collection instead of the original collection:
rule "shadow proxy on collections"
when
$list : ArrayList() from collect( Cheesery() )
then
Cheesery $c = (Cheesery) $list.get( 0 );
Cheese cheese = new Cheese( "stilton", 10 );
$c.getCheeses().add( cheese );
results.add( cheese );
end
So, if instead of getting the collection and add the cheese, a addCheese() method was
created into the Cheesery class, if would correctly delegate and add the object to the
correct collection:
rule "shadow proxy on collections"
when
$c : Cheesery()
then
Cheese cheese = new Cheese( "stilton", 10 );
$c.addCheese( cheese );
results.add( cheese );
end
Although, I know this "workaround" is not correct because shadow proxies should
not be exposed to custom user code like the consequence. What I'm not sure about is
how we can ensure no shadow proxy is exposed if we allow any arbitrary code to be used in
semantic code blocks like consequence and accumulate actions...
Probably we will need to catch known declarations like collect declarations and
pre-process them in the consequence, extracting shadow proxies, to avoid such behavior?
Modifications to list objects contained within a bean and carried out
during the execution of a rule are not reflected in the original list i.e. the changes are
lost between the instance available within the rule and that of the original bean
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Key: JBRULES-1115
URL:
http://jira.jboss.com/jira/browse/JBRULES-1115
Project: JBoss Rules
Issue Type: Bug
Security Level: Public(Everyone can see)
Components: Reteoo
Affects Versions: 4.0.0.GA
Environment: HP-UX java version "1.5.0.05"
Reporter: Anthony Dawson
Assigned To: Edson Tirelli
Fix For: 4.0.1
Modifications to list objects contained within a bean and carried out during the
execution of a rule are not reflected in the original list i.e. the changes are lost
between the instance available within the rule and that of the original bean
During the execution of the rules when I modify a list my changes are not reflected in my
bean.
Changes which affect simple objects like integers, strings etc are modified OK but lists
do not get updated in the bean.
Details of this problem are described in the forum messages.
http://www.nabble.com/How-to-limit-results-from-a-collect-statement-tf423...
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://jira.jboss.com/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira