[ mx4j-Bugs-1031741 ] Caching Support In Required Model MBean Is Broken

"SourceForge.net" <[email protected]>
Newsgroups gmane.comp.java.mx4j.devel
Message-ID <[email protected]>
Bugs item #1031741, was opened at 2004-09-21 18:41
Message generated for change (Comment added) made by jonseymour
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=450647&aid=1031741&group_id=47745

Category: JMX implementation
Group: None
Status: Open
Resolution: None
Priority: 5
Submitted By: Nobody/Anonymous (nobody)
Assigned to: Nobody/Anonymous (nobody)
Summary: Caching Support In Required Model MBean Is Broken

Initial Comment:
The following class is a JUnit test case which
demonstrates that two RequiredModelMBeans which share
the same ModelMBeanInfo class also share the same
attribute cache which leads to incorrect behaviour when
caching is enabled [ attribute values are aliased
between MBean instances ].

Both tests should pass, but only testWithoutCache does.

For more information about this testcase, write to
[email protected].


/*
 * Created on 21/09/2004
 *
 */
package bugs;

import javax.management.Attribute;
import javax.management.AttributeNotFoundException;
import javax.management.Descriptor;
import javax.management.InstanceNotFoundException;
import javax.management.InvalidAttributeValueException;
import javax.management.MBeanException;
import javax.management.ReflectionException;
import javax.management.modelmbean.DescriptorSupport;
import
javax.management.modelmbean.InvalidTargetObjectTypeException;
import javax.management.modelmbean.ModelMBeanAttributeInfo;
import
javax.management.modelmbean.ModelMBeanConstructorInfo;
import javax.management.modelmbean.ModelMBeanInfo;
import javax.management.modelmbean.ModelMBeanInfoSupport;
import
javax.management.modelmbean.ModelMBeanNotificationInfo;
import javax.management.modelmbean.ModelMBeanOperationInfo;
import javax.management.modelmbean.RequiredModelMBean;

import junit.framework.TestCase;

/**
 * @author jseymour
 *
 */
public class CachingBug
	extends TestCase
{
    private String foo;
    public String getFoo()
    {
        return foo;
    }
    public void setFoo(String foo) {
        this.foo = foo;
    }
    
    public void testWithoutCache() throws Exception {    
        theTest(false); 
    }
    
    public void testWithCache() throws Exception {    
        theTest(true); 
    }
    /**
     * @throws MBeanException
     * @throws InstanceNotFoundException
     * @throws InvalidTargetObjectTypeException
     * @throws AttributeNotFoundException
     * @throws InvalidAttributeValueException
     * @throws ReflectionException
     */
    private void theTest(boolean withCache) throws
MBeanException, InstanceNotFoundException,
InvalidTargetObjectTypeException,
AttributeNotFoundException,
InvalidAttributeValueException, ReflectionException {
        Descriptor d = new DescriptorSupport();
        
        if (withCache) {
            d.setField("currencyTimeLimit", "60");
        }
        
        d.setField("name", "foo");
        d.setField("descriptorType", "attribute");
        d.setField("getMethod", "getFoo");
        d.setField("setMethod", "setFoo");
        
        ModelMBeanAttributeInfo fooInfo = new
ModelMBeanAttributeInfo("foo", "java.lang.String", "is
a foo", true, true, false, d);
        ModelMBeanInfoSupport mbi = new
ModelMBeanInfoSupport(CachingBug.class.getName(),
"pojo", new ModelMBeanAttributeInfo[] { fooInfo } , new
ModelMBeanConstructorInfo[] {}, new
ModelMBeanOperationInfo[] {}, new
ModelMBeanNotificationInfo[] {} );
        RequiredModelMBean rmb1 = new
RequiredModelMBean(mbi);
        RequiredModelMBean rmb2 = new
RequiredModelMBean((ModelMBeanInfo)mbi.clone());
        
        CachingBug bar1 = new CachingBug();
        CachingBug bar2 = new CachingBug();
        
        rmb1.setManagedResource(bar1, "ObjectReference");
        rmb2.setManagedResource(bar2, "ObjectReference");
        
        rmb1.setAttribute(new Attribute("foo","bar1"));
        rmb2.setAttribute(new Attribute("foo","bar2"));
        assertEquals("value of rmb1.foo", "bar1",
rmb1.getAttribute("foo")); 
        assertEquals("value of rmb2.foo", "bar2",
rmb2.getAttribute("foo"));
    }
}


----------------------------------------------------------------------

Comment By: Jon Seymour (jonseymour)
Date: 2004-09-22 00:51

Message:
Logged In: YES 
user_id=1125728

The other thing worth noting about this bug/test case is
that the two mbeans actually don't share an identical
mbeaninfo - the 2nd mbean shares a clone of the first
mbean's mbeaninfo structure yet both  modelmbeans end up
sharing each other's attribute cache. This is ultimately
because ModelMBeanInfoSupport and DescriptorSupport don't
perform a deep enough clone.

The JMX specification may be quiet about dependencies
between cloned instances of metadata classes but it is not
clear to me that MX4J's chosen interpretation is
particularly useful.



----------------------------------------------------------------------

Comment By: Nobody/Anonymous (nobody)
Date: 2004-09-21 19:33

Message:
Logged In: NO 

Ok - I can see you are correct. Is there a reason why
ModelMBeanInfoSupport.clone() doesn't do a deep clone or at
least a clone that is deep enough to ensure that a cloned
ModelMBeanInfoSupport instance actually has its own
attribute cache?

----------------------------------------------------------------------

Comment By: Eamonn McManus (emcmanus)
Date: 2004-09-21 18:56

Message:
Logged In: YES 
user_id=770046

For better or worse, RequiredModelMBean is specified to
cache attribute values in the attribute Descriptor. If two
RequiredModelMBeans share the same ModelMBeanInfo, then they
share the same ModelMBeanAttributeInfos and therefore the
same Descriptors for their attributes. As a consequence, if
you enable attribute caching, you cannot share your
MBeanInfo with anyone else.

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=450647&aid=1031741&group_id=47745


-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170
Project Admins to receive an Apple iPod Mini FREE for your judgement on
who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.