[jboss-jira] [JBoss JIRA] Commented: (JBRULES-1115) 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

Edson Tirelli (JIRA) jira-events at lists.jboss.org
Fri Aug 24 14:58:33 EDT 2007


    [ 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-tf4235669.html#a12278683

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

        



More information about the jboss-jira mailing list